odysseus-dev/odysseus · warning · Error

Failed to archive session

Error message

Failed to archive session

What it means

Thrown by the archive action in sessions.js when POST /api/session/{id}/archive returns non-ok. The status and body are discarded entirely — the same fixed string is used both for the throw and the catch's showError, so 'Failed to archive session' carries no diagnostic information. The dropdown is simply left open.

Source

Thrown at static/js/sessions.js:926

    } catch (e) { /* network error — session may still exist server-side */ }
    await loadSessions();
  });

  archiveItem.addEventListener('click', async () => {
    dropdown.style.display = 'none';
    _forceSidebarOpen();
    try {
      const response = await fetch(`${API_BASE}/api/session/${s.id}/archive`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' }
      });
      if (response.ok) {
        _forceSidebarOpen();
        await loadSessions();
        dropdown.style.display = 'none';
        uiModule.showToast('Session archived');
      } else {
        throw new Error('Failed to archive session');
      }
    } catch (error) {
      console.error('Error archiving session:', error);
      uiModule.showError('Failed to archive session');
    }
  });

  // Dropdowns are closed by the shared global listener (_initDropdownDismiss)

  // Prevent dropdown from closing when clicking inside it
  dropdown.addEventListener('click', (e) => {
    e.stopPropagation();
  });

  div.appendChild(span);

  // Apply processing/completed state to the star dot
  var _isProcessing = _researchingSessions.has(s.id) || _streamingSessions.has(s.id);

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. Reload the session list (loadSessions) and retry on the current id.
  2. If cross-origin, add credentials:'same-origin' to the fetch (see exampleFix).
  3. Check server logs for the real status behind the generic message.
  4. Include the status in the error text for future diagnosability.

Example fix

// before
const response = await fetch(`${API_BASE}/api/session/${s.id}/archive`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' }
});
if (!response.ok) { throw new Error('Failed to archive session'); }

// after
const response = await fetch(`${API_BASE}/api/session/${s.id}/archive`, {
  method: 'POST',
  credentials: 'same-origin',
  headers: { 'Content-Type': 'application/json' }
});
if (!response.ok) { throw new Error(`Failed to archive session (HTTP ${response.status})`); }
Defensive patterns

Strategy: try-catch

Try / catch

try { if (!response.ok) throw new Error(`Failed to archive session (HTTP ${response.status})`); await loadSessions(); } catch (error) { uiModule.showError('Failed to archive session'); dropdown.style.display = 'none'; }

Prevention

When it happens

Trigger: Archiving a session id the server no longer has (404, deleted elsewhere); session store write failure (500); missing credentials header handling — note this fetch sends Content-Type but not credentials:'same-origin', so a strict cookie policy can yield 401/302.

Common situations: Stale session list after another device deleted the conversation; cross-origin deployment where same-origin credentials are required but not sent; backend storage locked.

Related errors


AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14). Data as JSON: /api/errors/418eaabb5a8e332c. Report an issue: GitHub.