{"record":{"id":"0d615c87248543c6","repo":"odysseus-dev/odysseus","slug":"errdata-detail-failed-to-create-session","errorCode":null,"errorMessage":"errData.detail || 'Failed to create session'","messagePattern":"errData\\.detail \\|\\| 'Failed to create session'","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"static/js/compare/stream.js","lineNumber":91,"sourceCode":"}\n\n/** Run synthesis for a search pane — sends search results to an LLM for analysis. */\nasync function _runSynthForPane(modelToUse, synthPrompt, synthBody, spinner, hist) {\n  // Create temp session for synthesis\n  const fd = new FormData();\n  fd.append('name', 'Synthesis');\n  fd.append('endpoint_url', modelToUse.endpoint || '');\n  fd.append('model', modelToUse.model || '');\n  if (modelToUse.endpointId) {\n    fd.append('endpoint_id', modelToUse.endpointId);\n    fd.append('skip_validation', 'true');\n  }\n\n  try {\n    const createRes = await fetch(`${state.API_BASE}/api/session`, { method: 'POST', body: fd });\n    if (!createRes.ok) {\n      const errData = await createRes.json().catch(() => ({}));\n      throw new Error(errData.detail || 'Failed to create session');\n    }\n    const createData = await createRes.json();\n\n    const synthAc = new AbortController();\n    state._abortControllers.push(synthAc);\n    const streamRes = await fetch(`${state.API_BASE}/api/chat_stream`, {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json' },\n      body: JSON.stringify({ session: createData.id, message: synthPrompt }),\n      signal: synthAc.signal,\n    });\n\n    if (spinner) spinner.stop();\n    synthBody.innerHTML = '';\n    const reader = streamRes.body.getReader();\n    const decoder = new TextDecoder();\n    let synthText = '';\n","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/static/js/compare/stream.js#L73-L109","documentation":"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.","triggerScenarios":"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'.","commonSituations":"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.","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"],"exampleFix":"// before\nconst errData = await createRes.json().catch(() => ({}));\nthrow new Error(errData.detail || 'Failed to create session');\n\n// after\nconst errData = await createRes.json().catch(() => ({}));\nthrow new Error(errData.detail || `Failed to create session (HTTP ${createRes.status})`);","handlingStrategy":"validation","validationCode":"if (!modelToUse || !(modelToUse.endpoint || modelToUse.endpointId) || !modelToUse.model) {\n  throw new Error('Select a model endpoint before running the comparison');\n}","typeGuard":null,"tryCatchPattern":"try {\n  const createRes = await fetch(`${state.API_BASE}/api/session`, { method: 'POST', body: fd });\n  if (!createRes.ok) {\n    const errData = await createRes.json().catch(() => ({}));\n    throw new Error(errData.detail || `Failed to create session (HTTP ${createRes.status})`);\n  }\n  const createData = await createRes.json();\n  // ... proceed to chat_stream\n} catch (e) {\n  state._abortControllers.length && state._abortControllers.pop();\n  showCompareError('Synthesis failed: ' + e.message);\n}","preventionTips":["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"],"tags":["fetch","http-error","session","form-validation","compare-mode"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}