odysseus-dev/odysseus · error · Error
errData.detail || 'Failed to create session'
Error message
errData.detail || 'Failed to create session'
What it means
Error thrown while creating the synthesis session in compare mode: POST /api/session (multipart form) returned a non-OK status, and the parsed JSON 'detail' (or a generic message) becomes the error text. It aborts the whole compare/synthesis stream before it starts.
Source
Thrown at static/js/compare/stream.js:91
}
/** Run synthesis for a search pane — sends search results to an LLM for analysis. */
async function _runSynthForPane(modelToUse, synthPrompt, synthBody, spinner, hist) {
// Create temp session for synthesis
const fd = new FormData();
fd.append('name', 'Synthesis');
fd.append('endpoint_url', modelToUse.endpoint || '');
fd.append('model', modelToUse.model || '');
if (modelToUse.endpointId) {
fd.append('endpoint_id', modelToUse.endpointId);
fd.append('skip_validation', 'true');
}
try {
const createRes = await fetch(`${state.API_BASE}/api/session`, { method: 'POST', body: fd });
if (!createRes.ok) {
const errData = await createRes.json().catch(() => ({}));
throw new Error(errData.detail || 'Failed to create session');
}
const createData = await createRes.json();
const synthAc = new AbortController();
state._abortControllers.push(synthAc);
const streamRes = await fetch(`${state.API_BASE}/api/chat_stream`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ session: createData.id, message: synthPrompt }),
signal: synthAc.signal,
});
if (spinner) spinner.stop();
synthBody.innerHTML = '';
const reader = streamRes.body.getReader();
const decoder = new TextDecoder();
let synthText = '';
View on GitHub (pinned to f9235ebbf1)
Solutions
- Inspect the response body of POST /api/session (curl -X POST with the same multipart fields) to see the validation 'detail'
- Confirm modelToUse.endpoint / modelToUse.model are non-empty and the endpoint_id still exists in the endpoints list
- Check server logs for the 4xx/5xx stack trace on session creation
- If 422, compare the form field names the backend expects (name, endpoint_url, model, endpoint_id) with what is appended
Example fix
// before
const errData = await createRes.json().catch(() => ({}));
throw new Error(errData.detail || 'Failed to create session');
// after
const errData = await createRes.json().catch(() => ({}));
throw new Error(errData.detail || `Failed to create session (HTTP ${createRes.status})`); Defensive patterns
Strategy: validation
Validate before calling
if (!modelToUse || !(modelToUse.endpoint || modelToUse.endpointId) || !modelToUse.model) {
throw new Error('Select a model endpoint before running the comparison');
} Try / catch
try {
const createRes = await fetch(`${state.API_BASE}/api/session`, { method: 'POST', body: fd });
if (!createRes.ok) {
const errData = await createRes.json().catch(() => ({}));
throw new Error(errData.detail || `Failed to create session (HTTP ${createRes.status})`);
}
const createData = await createRes.json();
// ... proceed to chat_stream
} catch (e) {
state._abortControllers.length && state._abortControllers.pop();
showCompareError('Synthesis failed: ' + e.message);
} Prevention
- Validate the model selection (endpoint + model) before building the form
- Include the HTTP status in the fallback message so silent bodies are diagnosable
- Clean up any pushed AbortController when creation fails before the stream starts
When it happens
Trigger: POST /api/session fails with 422 (missing/invalid form fields such as name, endpoint_url, model), 400 (endpoint_id references a deleted endpoint), or 500. Then errData.detail is undefined when the body is not JSON, yielding the generic 'Failed to create session'.
Common situations: Selected model endpoint was removed or is unreachable so server-side validation rejects it; endpoint_id passed with skip_validation=true points to a stale row; required form field missing after a UI change; backend version mismatch on the /api/session contract.
Related errors
- detail || ('HTTP ' + res.status)
- 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/0d615c87248543c6.
Report an issue: GitHub.