bytedance/deer-flow · warning · HTTPException
Thread has a run in flight. Set the goal after the run…
Error message
Thread has a run in flight. Set the goal after the run finishes.
What it means
409 from PUT /threads/{thread_id}/goal when reserve_checkpoint_write raises ConflictError — the thread currently has an in-flight run holding the checkpoint write reservation, and goal writes are excluded to avoid clobbering live state. The error is deliberate serialization, telling the caller to wait.
Solutions
- Wait for the active run to finish (poll GET /threads/{id} status or the stream completion) and retry the PUT.
- In the UI, disable goal editing while the thread status is not idle.
- If no run is actually active but the 409 persists, the reservation leaked — restart the Gateway or clear the reservation state per its docs, then retry.
- Sequence goal updates between runs in automation rather than racing them.
Example fix
// before
await api.put(`/threads/${id}/goal`, {objective}); // 409 during a run
// after
let s = await api.get(`/threads/${id}`).status;
while (s !== 'idle') { await waitForRunCompletion(id); s = (await api.get(`/threads/${id}`)).status; }
await api.put(`/threads/${id}/goal`, {objective}); Defensive patterns
Strategy: retry
Validate before calling
const {status} = await api.get(`/api/threads/${id}`);
if (status !== 'idle') { /* queue the goal update; PUT after the run completes */ } Type guard
async function threadIdle(id: string): Promise<boolean> {
const t = await api.get(`/api/threads/${id}`);
return t.status === 'idle';
} Try / catch
try { await api.put(`/api/threads/${id}/goal`, body); }
catch (err) {
if (err.status === 409 && /run in flight/.test(err.detail)) { await waitForRunCompletion(id); retryOnce(); }
else throw err;
} Prevention
- Disable goal editing in the UI while the thread is streaming/running.
- Sequence goal updates between runs in automation instead of racing them.
- A persistent 409 with no visible run indicates a leaked reservation — restart the Gateway rather than retrying harder.
When it happens
Trigger: PUT /goal while a run/stream on the same thread is executing (agent streaming a response, background goal continuation active), or a stale reservation left by a run that died without releasing.
Common situations: User edits the goal in the UI while the agent is mid-run; automated loops setting goals concurrently with runs; a crashed worker whose reservation was not reclaimed yet.
Related errors
- Branching is only available in the main conversation.
- Thread has a run in flight. Save after the run finishes.
- Agent ' ' already exists
- Failed to create thread
- Failed to create thread checkpoint
AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14).
Data as JSON: /api/errors/74ace1ad67cdd341.
Report an issue: GitHub.
Appendix: source
Thrown at backend/app/gateway/routers/threads.py:1105
@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:
raise HTTPException(status_code=422, detail=str(exc)) from exc
except ConflictError:
raise HTTPException(status_code=409, detail="Thread has a run in flight. Set the goal after the run finishes.") from None
except HTTPException:
raise
except Exception:
logger.exception("Failed to set goal for thread %s", sanitize_log_param(thread_id))
raise HTTPException(status_code=500, detail="Failed to set thread goal") from None
return ThreadGoalResponse(goal=goal)
@router.delete("/{thread_id}/goal", response_model=ThreadGoalResponse)
@require_permission("threads", "write", owner_check=True)
async def clear_thread_goal(thread_id: ThreadId, request: Request) -> ThreadGoalResponse:
"""Clear the active goal for a thread."""
checkpointer = get_checkpointer(request)
try:
async with reserve_checkpoint_write(request, thread_id, user_id=get_effective_user_id()):
await write_thread_goal(checkpointer, thread_id, None, as_node="goal")
except ConflictError:
raise HTTPException(status_code=409, detail="Thread has a run in flight. Clear the goal after the run finishes.") from NoneView on GitHub (pinned to 1dd6ba1acb)