odysseus-dev/odysseus · error · Error
detail || ('HTTP ' + res.status)
Error message
detail || ('HTTP ' + res.status) What it means
Custom client-side Error thrown by the 'Discuss' button in the chat renderer after POST /api/research/spinoff/{sessionId} returns a non-OK HTTP status. The server's JSON 'detail' field (FastAPI-style error body) is used as the message, falling back to the bare status code. It means the backend refused or failed to create a follow-up chat session for the research report.
Source
Thrown at static/js/chatRenderer.js:1255
window.open(reportUrl, '_blank');
});
wrap.appendChild(btn);
var chatBtn = document.createElement('button');
chatBtn.type = 'button';
chatBtn.className = 'view-report-btn chat-about-btn';
chatBtn.innerHTML = CHAT_ABOUT_ICON + ' Discuss';
chatBtn.addEventListener('click', async function() {
if (chatBtn.disabled) return;
var origLabel = chatBtn.innerHTML;
chatBtn.disabled = true;
chatBtn.innerHTML = CHAT_ABOUT_ICON + ' Creating…';
try {
var res = await fetch(apiBase + '/api/research/spinoff/' + sessionId, { method: 'POST' });
if (!res.ok) {
var detail = '';
try { detail = (await res.json()).detail || ''; } catch {}
throw new Error(detail || ('HTTP ' + res.status));
}
var payload = await res.json();
if (window.sessionModule && payload.session_id) {
await window.sessionModule.loadSessions().catch(() => {});
await window.sessionModule.selectSession(payload.session_id);
}
} catch (e) {
chatBtn.disabled = false;
chatBtn.innerHTML = origLabel;
if (window.uiModule && uiModule.showError) {
uiModule.showError('Could not start follow-up chat: ' + e.message);
} else {
alert('Could not start follow-up chat: ' + e.message);
}
}
});
wrap.appendChild(chatBtn);
View on GitHub (pinned to f9235ebbf1)
Solutions
- Check the server logs for the actual exception behind the non-OK status of POST /api/research/spinoff/{sessionId}
- Verify the sessionId still exists (GET the session list) and reload the page to pick up a fresh id
- If the body has no 'detail', reproduce with curl -i -X POST .../api/research/spinoff/<id> to see the raw status and body
- Handle 404 specifically by informing the user the report session is gone and offering a reload
Example fix
// before
var detail = '';
try { detail = (await res.json()).detail || ''; } catch {}
throw new Error(detail || ('HTTP ' + res.status));
// after
var detail = '';
try { detail = (await res.json()).detail || ''; } catch {}
if (res.status === 404) throw new Error('Report session no longer exists — reload the page');
throw new Error(detail || ('HTTP ' + res.status + ' ' + res.statusText)); Defensive patterns
Strategy: try-catch
Validate before calling
if (!sessionId) { uiModule.showError('No report session loaded'); return; } Try / catch
try {
const res = await fetch(apiBase + '/api/research/spinoff/' + encodeURIComponent(sessionId), { method: 'POST' });
if (!res.ok) {
const detail = await res.json().then(d => d.detail).catch(() => '');
if (res.status === 404) throw new Error('Report session no longer exists — reload');
throw new Error(detail || `HTTP ${res.status} ${res.statusText}`);
}
const payload = await res.json();
if (window.sessionModule && payload.session_id) {
await window.sessionModule.loadSessions().catch(() => {});
await window.sessionModule.selectSession(payload.session_id);
}
} catch (e) {
chatBtn.disabled = false;
chatBtn.innerHTML = origLabel;
(window.uiModule?.showError || console.error)('Could not start follow-up chat: ' + e.message);
} Prevention
- URL-encode sessionId in the path to avoid malformed-route 404s
- Disable the button only during flight and always restore it in finally-style cleanup
- Treat 404 as stale session and prompt a reload instead of a generic error
When it happens
Trigger: POST /api/research/spinoff/{sessionId} responds 4xx/5xx: sessionId no longer exists (404), server error while deriving the spinoff session (500), or an empty 'detail' field in the error body so only 'HTTP <status>' is shown.
Common situations: Session was deleted or expired between viewing the report and clicking Discuss; backend restarted and lost in-memory session state; research artifacts missing on disk; auth/session cookie expired.
Related errors
- errData.detail || 'Failed to create session'
- HTTP ${response.status}
- HTTP ${res.status} ${res.statusText}${msg ? `: ${msg}` : ''}
- data.detail || data.error || `HTTP ${res.status}`
- HTTP ${res.status}
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/c6389fa69a3f239e.
Report an issue: GitHub.