bytedance/deer-flow · error · HTTPException

Failed to read thread goal

Error message

Failed to read thread goal

What it means

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.

Source

Thrown at backend/app/gateway/routers/threads.py:1084

        thread_id=thread_id,
        status=status,
        created_at=coerce_iso(record.get("created_at", "")),
        updated_at=coerce_iso(record.get("updated_at", "")),
        metadata=record.get("metadata", {}),
        values=serialize_channel_values_for_api(snapshot.values),
    )


@router.get("/{thread_id}/goal", response_model=ThreadGoalResponse)
@require_permission("threads", "read", owner_check=True)
async def get_thread_goal(thread_id: ThreadId, request: Request) -> ThreadGoalResponse:
    """Return the active Claude-style goal for a thread, if any."""
    checkpointer = get_checkpointer(request)
    try:
        goal = await read_thread_goal(checkpointer, thread_id)
    except Exception:
        logger.exception("Failed to read goal for thread %s", sanitize_log_param(thread_id))
        raise HTTPException(status_code=500, detail="Failed to read thread goal") from None
    return ThreadGoalResponse(goal=goal)


@router.put("/{thread_id}/goal", response_model=ThreadGoalResponse)
@require_permission("threads", "write", owner_check=True)
async def set_thread_goal(thread_id: ThreadId, body: ThreadGoalRequest, request: Request) -> ThreadGoalResponse:
    """Set or replace the active goal for a thread.

    ``/chats/new`` pages already hold a generated UUID before the first run, so
    this endpoint creates the missing thread checkpoint on demand.
    """
    checkpointer = get_checkpointer(request)
    try:
        goal = build_goal_state(body.objective, max_continuations=body.max_continuations)
        async with reserve_checkpoint_write(request, thread_id, user_id=get_effective_user_id()):
            await _ensure_thread_for_goal(thread_id, request)
            await write_thread_goal(checkpointer, thread_id, goal, as_node="goal", create_if_missing=True)
    except ValueError as exc:

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Check the 'Failed to read goal for thread %s' traceback for the storage-level cause.
  2. Restore checkpoint DB health / align serializer versions.
  3. Retry the GET — it is read-only.
  4. If the goal blob itself is corrupt, clearing the goal (DELETE /goal) may fail similarly; delete the thread's checkpoints as a last resort.
Defensive patterns

Strategy: retry

Try / catch

try { const {goal} = await api.get(`/api/threads/${id}/goal`); }
catch (err) { if (err.status === 500) { await backoff(); retryOnce(); } else throw err; } // read-only, retry is safe

Prevention

When it happens

Trigger: 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.

Common situations: DB outage; serializer/checkpoint version mismatch after upgrade; corrupt goal checkpoint row; lock contention with a concurrent run writing the same thread.

Related errors


AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14). Data as JSON: /api/errors/9cf38e298e5feb9b. Report an issue: GitHub.