โ† Dashboard ยท Docs ยทChat Loading Issue

> STATUS: RESOLVED (as of build e6c937427256, 2026-06-07). The JS-syntax/script-block fragmentation issue described below no longer applies. The dashboard template was extracted from web.py into assets/dashboard.html (13,633 lines as of this build); all chat JS functions (loadChat, sendChat, groveFetch, loadChatConversations, switchTab) are present and at stable line numbers in that file (loadChat ~3570, sendChat ~12653, groveFetch ~12528, loadChatConversations ~12841). The multi-script-block layout referenced below (blocks at lines 8384, 10944, 11504 of web.py) no longer exists. The window.onerror title handler is retained at dashboard.html ~1544. This file is retained as a historical incident record.

Chat Loading Issue โ€” Cell Dashboard

Symptom

On the cell dashboard chat tab:

1. Selecting a peer from the dropdown shows "Loading chat..." forever โ€” messages never render

2. The expandable "Conversations" list also shows "Loading..." and never populates

3. No requests for /api/chat or /api/chat/conversations appear in server logs at all

What Was Working Before

Chat was working earlier in the session. The issue appeared after a series of UI changes were made to the chat tab:

Key Observation

No HTTP requests reach the server. The Flask logs show zero hits to /api/chat or /api/chat/conversations. This means the JS is failing silently before making the fetch call. A hard refresh (Cmd+Shift+R) does not fix it, ruling out simple caching.

Likely Causes

1. JS error in an earlier script block kills execution

The cell dashboard has multiple <script> blocks. An error in one block can prevent later blocks from executing. Key script blocks and their line ranges:

If the script block at 11504 has a syntax error, groveFetch won't be defined, and loadChat (which calls groveFetch at line 9428) will throw a ReferenceError when invoked.

2. Template rendering error

Jinja2 template variables inside JS strings could produce invalid JS. For example, an unescaped ' in a peer name or config value could break a string literal and kill the entire script block.

3. loadChatConversations or nearby code has a syntax issue

The function was added at line ~12389. Even though brace counting shows balanced {}s, there could be other syntax issues (unclosed template literals, bad escaping, etc.).

Investigation Already Done

Brace counting โ€” balanced

Python script checked all script blocks containing the chat code. Both blocks (8384-9482 and 11504-12641) have perfectly balanced { and } counts. So it's not a missing brace.

Server is healthy

The Flask server is running and responding to other API calls (/api/version, /api/health, /api/pubkey all return 200). The issue is purely client-side โ€” JS fails before making any fetch.

Hard refresh doesn't help

Cmd+Shift+R was tried โ€” same result. Rules out stale cached JS. The rendered HTML from the server has the broken code.

window.onerror handler exists

Line 8359 has: window.onerror=function(m,s,l,c,e){document.title='ERR L'+l+' C'+c+': '+m;} โ€” if a JS error occurs, the page title should change to show the error line/column. Check the browser tab title for ERR L... text.

Changes Made in This Session (Chronological)

These are all the chat-related edits made before the break occurred, in order. The bug was introduced somewhere in this sequence:

1. Sync globals + timestamp tracking โ€” Added _last_sync_time, _last_sync_ok globals, updated opp_sync_loop and manual sync to record timestamps. (Backend only, unlikely cause.)

2. /api/network-health endpoint โ€” New API endpoint returning My Data / My Cell / sync status. (Backend only.)

3. Network Health HTML revamp โ€” Replaced old health section with new My Data / My Cell / last sync layout, moved Sync Now and Prune buttons. (HTML only, in dashboard template but outside chat tab.)

4. loadStorageBreakdown JS rewrite โ€” Changed from fetching /api/replication-summary to /api/network-health. This is in the script block at 11504-12641 โ€” same block as groveFetch, sendChat, and loadChatConversations. A syntax error here would kill the entire block.

5. _last_sync_time / _last_sync_ok in manual sync โ€” Backend only.

6. /api/exchange-secret auth relaxation โ€” Backend only.

7. Chat queue + retry (_retry_undelivered_chat) โ€” Backend only.

8. send_message refactor โ€” Changed pubkey resolution to try config first (offline support), added encryption pubkey caching, changed response to return queued: true. Backend + response format change.

9. sendChat JS rewrite โ€” Added "sending..." indicator, disabled button during send, swapped from inline message append to a two-phase approach (show sending div, then replace with final). This is in script block 11504-12641. Template literal changes here could have syntax issues.

10. loadChat changes โ€” Added container.innerHTML = 'Loading chat...' at the top, and added GroveAI immediate UI render. This is in script block 8384-9482. If this block has an error, loadChat itself won't be defined.

11. Duplicate handler removal โ€” Removed onclick and onkeydown inline attributes from chat input/button. (HTML only.)

12. Conversations list โ€” Added <details> HTML, /api/chat/conversations endpoint, loadChatConversations JS function, selectConversation JS function. JS in script block 11504-12641.

13. switchTab modification โ€” Added if (tab === 'chat') setTimeout(...) call to loadChatConversations. This is in script block 8384-9482.

14. Prune button label / alignment changes โ€” HTML + JS in different script block (prune is in 8384-9482 area). The checkPruneStatus JS change modified button text โ€” low risk but in the same script block as loadChat.

Debug Steps

Step 1: Check browser tab title

If window.onerror fired, the tab title will show something like ERR L12345 C67: Unexpected token. This gives exact line and column of the error.

Step 2: Open browser console

Open dev tools (Cmd+Option+I on Mac, or right-click โ†’ Inspect โ†’ Console). Look for red errors:

Step 3: Check which functions exist

In browser console, type:


typeof groveFetch           // 'function' if script block 11504 is OK
typeof loadChat             // 'function' if script block 8384 is OK
typeof sendChat             // 'function' if script block 11504 is OK
typeof loadChatConversations // 'function' if conversations code is OK
typeof switchTab            // 'function' if script block 8384 is OK

If any returns 'undefined', that script block is broken.

Step 4: Test API endpoints directly

Open these URLs in the browser (must be logged into dashboard):


http://localhost:5678/api/chat/conversations
http://localhost:5678/api/chat?peer=100.126.143.83

If they return JSON, the backend is fine and the problem is purely JS.

Step 5: Bisect the problem

Since we know chat was working before these changes and the most likely culprit is a JS syntax error in one of the script blocks:

Option A โ€” Remove conversations code:

Delete the loadChatConversations function, selectConversation function, the <details> HTML, and the switchTab chat hook. If chat loading recovers, the conversations code has a syntax error.

Option B โ€” Check the sendChat rewrite:

The sendChat function was heavily rewritten with template literals containing ${} interpolation. Jinja2 also uses ${} is not a conflict, but {{ }} IS โ€” if any Jinja variable accidentally appears inside a JS template literal in this block, it would cause a syntax error. Search for {{ inside the script block at lines 11504-12641.

Option C โ€” Render the dashboard HTML and search for syntax errors:


# Save the rendered dashboard HTML
curl -s -b <session-cookie> http://localhost:5678/dashboard > /tmp/dashboard.html
# Extract the suspect script block and lint it
# Or just search for obvious issues
grep -n 'SyntaxError\|undefined\|NaN' /tmp/dashboard.html

Step 6: Nuclear option

If debugging is taking too long, revert web.py to the last known-good commit (before chat changes) using:


git stash  # save current changes
git log --oneline -10  # find the good commit
git checkout <hash> -- web.py  # restore just web.py

Then re-apply changes one at a time to find which one breaks chat.

Code Locations

Function Line Script Block Purpose
switchTab() ~8405 8384-9482 Tab switching, triggers chat load
loadChat() ~9392 8384-9482 Loads chat for selected peer
checkPruneStatus() ~8753 8384-9482 Updates prune button text
fallbackSend() ~10971 10944-11015 Isolated chat form handler
groveFetch() ~12103 11504-12641 Auth-aware fetch wrapper
sendChat() ~12211 11504-12641 Primary chat send function
loadChatConversations() ~12389 11504-12641 Conversations list loader
loadStorageBreakdown() ~12105 11504-12641 Network health data loader
/api/chat ~19876 โ€” Chat messages endpoint
/api/chat/conversations ~19914 โ€” Conversations list endpoint

Notes