{"record":{"id":"615448a7ef6dd0d0","repo":"odysseus-dev/odysseus","slug":"session-id-original-text-and-instruction-are-req","errorCode":null,"errorMessage":"session_id, original_text, and instruction are required","messagePattern":"session_id, original_text, and instruction are required","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"routes/chat_routes.py","lineNumber":2494,"sourceCode":"    # ------------------------------------------------------------------ #\n    @router.post(\"/api/rewrite\")\n    async def rewrite_message(request: Request) -> StreamingResponse:\n        \"\"\"Rewrite the last AI message with an instruction (shorter/simpler/etc).\n\n        Unlike the full chat pipeline, this does NOT run the agent loop or tools.\n        It just asks the LLM to rewrite the given text.\n        \"\"\"\n        try:\n            body = await request.json()\n        except Exception:\n            raise HTTPException(400, \"Invalid JSON\")\n\n        session_id = body.get(\"session_id\")\n        original_text = body.get(\"original_text\", \"\")\n        instruction = body.get(\"instruction\", \"\")\n\n        if not session_id or not original_text or not instruction:\n            raise HTTPException(400, \"session_id, original_text, and instruction are required\")\n\n        _verify_session_owner(request, session_id)\n\n        try:\n            sess = session_manager.get_session(session_id)\n        except (KeyError, SessionNotFoundError):\n            raise HTTPException(404, \"Session not found\")\n\n        messages = [\n            {\"role\": \"system\", \"content\": (\n                \"You are rewriting a previous response. Follow the instruction exactly. \"\n                \"Output ONLY the rewritten text — no preamble, no explanation, no meta-commentary. \"\n                \"Preserve any formatting (markdown, code blocks, lists) from the original.\"\n            )},\n            {\"role\": \"user\", \"content\": (\n                f\"Here is the original response:\\n\\n{original_text}\\n\\n\"\n                f\"Instruction: {instruction}\"\n            )},","sourceCodeStart":2476,"sourceCodeEnd":2512,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/routes/chat_routes.py#L2476-L2512","documentation":"POST /api/rewrite validated the JSON successfully but at least one of the three required fields — session_id, original_text, instruction — is missing or empty (falsy). All three are mandatory because the endpoint rewrites a specific prior message under a specific instruction.","triggerScenarios":"Calling /api/rewrite with an empty instruction, no session_id, or original_text of \"\" (note: original_text defaults to '' so omitting it always fails this check).","commonSituations":"UI 'rewrite' button firing before the user typed an instruction; state bugs leaving original_text empty when the last AI message wasn't captured; API callers assuming fields are optional.","solutions":["Include all three non-empty fields: session_id, original_text, and instruction","Disable the rewrite action in the UI until an instruction is entered","When wiring the button, pass the exact last assistant message text as original_text"],"exampleFix":"// before\nfetch('/api/rewrite', {method:'POST', headers, body: JSON.stringify({session_id: id, instruction})})\n// after\nfetch('/api/rewrite', {method:'POST', headers, body: JSON.stringify({session_id: id, original_text: lastAiText, instruction: instruction.trim()})})","handlingStrategy":"validation","validationCode":"if (!session_id || !original_text?.trim() || !instruction?.trim()) {\n  showValidationError('session_id, original_text, and instruction are required'); return;\n}\nawait postRewrite({session_id, original_text, instruction});","typeGuard":"function isValidRewritePayload(p: unknown): p is {session_id: string; original_text: string; instruction: string} {\n  const o = p as any;\n  return typeof o?.session_id === 'string' && o.session_id.length > 0\n      && typeof o?.original_text === 'string' && o.original_text.length > 0\n      && typeof o?.instruction === 'string' && o.instruction.trim().length > 0;\n}","tryCatchPattern":null,"preventionTips":["Disable the rewrite button until an instruction is entered","Capture the exact last assistant message text as original_text when rendering it"],"tags":["validation","rewrite","client-error","fastapi"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}