{"record":{"id":"9cf38e298e5feb9b","repo":"bytedance/deer-flow","slug":"failed-to-read-thread-goal","errorCode":null,"errorMessage":"Failed to read thread goal","messagePattern":"Failed to read thread goal","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"backend/app/gateway/routers/threads.py","lineNumber":1084,"sourceCode":"        thread_id=thread_id,\n        status=status,\n        created_at=coerce_iso(record.get(\"created_at\", \"\")),\n        updated_at=coerce_iso(record.get(\"updated_at\", \"\")),\n        metadata=record.get(\"metadata\", {}),\n        values=serialize_channel_values_for_api(snapshot.values),\n    )\n\n\n@router.get(\"/{thread_id}/goal\", response_model=ThreadGoalResponse)\n@require_permission(\"threads\", \"read\", owner_check=True)\nasync def get_thread_goal(thread_id: ThreadId, request: Request) -> ThreadGoalResponse:\n    \"\"\"Return the active Claude-style goal for a thread, if any.\"\"\"\n    checkpointer = get_checkpointer(request)\n    try:\n        goal = await read_thread_goal(checkpointer, thread_id)\n    except Exception:\n        logger.exception(\"Failed to read goal for thread %s\", sanitize_log_param(thread_id))\n        raise HTTPException(status_code=500, detail=\"Failed to read thread goal\") from None\n    return ThreadGoalResponse(goal=goal)\n\n\n@router.put(\"/{thread_id}/goal\", response_model=ThreadGoalResponse)\n@require_permission(\"threads\", \"write\", owner_check=True)\nasync def set_thread_goal(thread_id: ThreadId, body: ThreadGoalRequest, request: Request) -> ThreadGoalResponse:\n    \"\"\"Set or replace the active goal for a thread.\n\n    ``/chats/new`` pages already hold a generated UUID before the first run, so\n    this endpoint creates the missing thread checkpoint on demand.\n    \"\"\"\n    checkpointer = get_checkpointer(request)\n    try:\n        goal = build_goal_state(body.objective, max_continuations=body.max_continuations)\n        async with reserve_checkpoint_write(request, thread_id, user_id=get_effective_user_id()):\n            await _ensure_thread_for_goal(thread_id, request)\n            await write_thread_goal(checkpointer, thread_id, goal, as_node=\"goal\", create_if_missing=True)\n    except ValueError as exc:","sourceCodeStart":1066,"sourceCodeEnd":1102,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/app/gateway/routers/threads.py#L1066-L1102","documentation":"500 from GET /threads/{thread_id}/goal when read_thread_goal(checkpointer, thread_id) raises — reading the goal node's state out of the checkpointer failed with an unexpected exception. The traceback is logged with the thread id; a thread with no goal returns a null goal, not an error, so this is strictly a storage/read failure.","triggerScenarios":"GET the goal while checkpoint storage is unreachable, the goal state blob fails to deserialize, or the checkpointer raises a non-mode error during aget.","commonSituations":"DB outage; serializer/checkpoint version mismatch after upgrade; corrupt goal checkpoint row; lock contention with a concurrent run writing the same thread.","solutions":["Check the 'Failed to read goal for thread %s' traceback for the storage-level cause.","Restore checkpoint DB health / align serializer versions.","Retry the GET — it is read-only.","If the goal blob itself is corrupt, clearing the goal (DELETE /goal) may fail similarly; delete the thread's checkpoints as a last resort."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { const {goal} = await api.get(`/api/threads/${id}/goal`); }\ncatch (err) { if (err.status === 500) { await backoff(); retryOnce(); } else throw err; } // read-only, retry is safe","preventionTips":["Cache the goal client-side from the PUT response so GETs are rare.","Treat single-thread 500s as possible corruption; global 500s as outage."],"tags":["threads","goals","checkpointer","http-500"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}