{"record":{"id":"c52db02dc6b1fb4a","repo":"odysseus-dev/odysseus","slug":"failed-to-create-task","errorCode":null,"errorMessage":"Failed to create task","messagePattern":"Failed to create task","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"static/js/tasks.js","lineNumber":79,"sourceCode":"    await fetch(`${API_BASE}/api/tasks/onboarding`, {\n      method: 'POST',\n      credentials: 'same-origin',\n      headers: { 'Content-Type': 'application/json' },\n      body: JSON.stringify({ enabled: false }),\n    });\n  } catch (e) {\n    console.warn('Tasks onboarding failed:', e);\n  }\n}\n\nasync function _createTask(data) {\n  const res = await fetch(`${API_BASE}/api/tasks`, {\n    method: 'POST',\n    credentials: 'same-origin',\n    headers: { 'Content-Type': 'application/json' },\n    body: JSON.stringify(data),\n  });\n  if (!res.ok) throw new Error('Failed to create task');\n  return await res.json();\n}\n\nasync function _updateTask(id, data) {\n  const res = await fetch(`${API_BASE}/api/tasks/${id}`, {\n    method: 'PUT',\n    credentials: 'same-origin',\n    headers: { 'Content-Type': 'application/json' },\n    body: JSON.stringify(data),\n  });\n  if (!res.ok) throw new Error('Failed to update task');\n  return await res.json();\n}\n\nasync function _deleteTask(id) {\n  const res = await fetch(`${API_BASE}/api/tasks/${id}`, {\n    method: 'DELETE', credentials: 'same-origin',\n  });","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/static/js/tasks.js#L61-L97","documentation":"Thrown by _createTask in static/js/tasks.js:79 when POST /api/tasks returns non-2xx. The status and server detail are discarded — the caller only ever sees 'Failed to create task'. The backend router (routes/task_routes.py, prefix /api/tasks) validates the task body (action, schedule, prompt fields) and is behind the interactive/auth gates.","triggerScenarios":"Creating a task from the tasks UI: POST JSON task definition. 422 when the payload shape is wrong (unknown action, invalid schedule expression, missing prompt), 401/403 when unauthenticated or gated (app.py gates /api/tasks), 500 on persistence failure.","commonSituations":"Invalid cron/schedule string; action name not in the server's registry; session expired; sending client-composed extra fields the schema forbids after a backend update.","solutions":["Replay the POST in devtools and read the 422 body — it names the invalid field (schedule, action, etc.).","Pick action values from /api/tasks/meta/actions rather than hardcoding.","Validate the schedule format client-side before submit.","Re-login on 401 and retry."],"exampleFix":"// before\nif (!res.ok) throw new Error('Failed to create task');\n// after\nconst d = await res.json().catch(() => ({}));\nif (!res.ok) throw new Error(d.detail ? (typeof d.detail === 'string' ? d.detail : JSON.stringify(d.detail)) : `Failed to create task (HTTP ${res.status})`);","handlingStrategy":"try-catch","validationCode":"if (!data || typeof data !== 'object' || !data.action) { throw new Error('Task payload must include an action'); } // ideally fetch valid actions first: await fetch(`${API_BASE}/api/tasks/meta/actions`)","typeGuard":"/** @returns {boolean} task payload has the fields POST /api/tasks requires */\nfunction isValidTaskPayload(p) {\n  return !!p && typeof p === 'object' && typeof p.action === 'string' && p.action.length > 0\n    && (p.schedule === undefined || typeof p.schedule === 'string');\n}","tryCatchPattern":"try { return await _createTask(data); } catch (err) { showError(err.message); /* keep the compose form populated for retry */ }","preventionTips":["Derive action choices from /api/tasks/meta/actions instead of hardcoding.","Validate schedule strings (cron) client-side before submit.","Preserve the compose form on failure so the user can retry.","Include the server 422 detail in the thrown error."],"tags":["fetch","api","http","tasks","validation"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}