bytedance/deer-flow · error · HTTPException
Thread has a run in flight. Save after the run finishes.
Error message
Thread has a run in flight. Save after the run finishes.
What it means
The artifacts PUT/update route translates a harness ConflictError into HTTP 409 with this message. The artifact store refuses writes while the owning thread has an active run, because the run may mutate or read the same file and an overwrite would race it.
Source
Thrown at backend/app/gateway/routers/artifacts.py:484
if not bool(getattr(sandbox_provider, "uses_thread_data_mounts", False)):
sandbox_id = await sandbox_provider.acquire_async(thread_id, user_id=effective_user_id)
sandbox = sandbox_provider.get(sandbox_id)
if sandbox is None:
raise RuntimeError("Failed to acquire sandbox for artifact update")
try:
if sandbox is not None:
await asyncio.to_thread(_sync_artifact_to_sandbox, sandbox, virtual_path, updated)
await asyncio.to_thread(_replace_artifact_atomically, actual_path, updated, file_stat)
except Exception:
if sandbox is not None:
try:
await asyncio.to_thread(_sync_artifact_to_sandbox, sandbox, virtual_path, current)
except Exception:
logger.exception("Failed to roll back remote artifact after artifact update failure: %s", virtual_path)
raise
except ConflictError:
raise HTTPException(status_code=409, detail="Thread has a run in flight. Save after the run finishes.") from None
except HTTPException:
raise
except Exception:
logger.exception("Failed to update artifact %s for thread %s", path, thread_id)
raise HTTPException(status_code=500, detail="Failed to update artifact") from None
finally:
if sandbox_id is not None and sandbox_provider is not None:
try:
await asyncio.to_thread(sandbox_provider.release, sandbox_id)
except Exception:
logger.warning("Failed to release sandbox after artifact update: %s", sandbox_id, exc_info=True)
content_sha256 = hashlib.sha256(updated).hexdigest()
return ArtifactUpdateResponse(
path=virtual_path,
sha256=content_sha256,
size=len(updated),
)View on GitHub (pinned to 1dd6ba1acb)
Solutions
- Wait for the run to finish (run status endpoint / stream 'end' event) and retry the save
- If the UI knows a run is active, disable the save button or buffer the edit and auto-save on run completion
- If no run should be active, check for orphaned run state in the thread and finalize it (restart Gateway if the run registry is stale in-memory state)
- Do not retry in a tight loop: poll run status and save once it reports idle
Example fix
// before
await saveArtifact(threadId, path, content); // fires during streaming
// after
if (isRunActive(threadId)) {
queueEdit(threadId, path, content); // replayed on run end event
} else {
await saveArtifact(threadId, path, content);
} Defensive patterns
Strategy: retry
Validate before calling
const run = await getActiveRun(threadId);
if (run && run.status !== 'ended') {
throw new Error('Thread has a run in flight; defer save');
} Try / catch
try {
await saveArtifact(threadId, path, content);
} catch (e) {
if (e.status === 409) { await waitForRunEnd(threadId); await saveArtifact(threadId, path, content); return; }
throw e;
} Prevention
- Subscribe to the thread's run/stream events and gate the editor save action on run-idle state
- Buffer edits made during a run and flush them exactly once on the run-end event
When it happens
Trigger: PUT or PATCH on /api/threads/{thread_id}/artifacts/{path} while a run/stream for that thread is in flight (agent still executing, or a previous run was not fully finalized). Editing a file in the UI while generation is streaming is the canonical case.
Common situations: User edits an artifact in the frontend editor while the agent is still generating; a stale frontend believes the run ended but the backend has not released the run lock; long-running tool execution keeps the run open for minutes.
Related errors
- Thread has a run in flight. Set the goal after the run finis
- HTTP ${response.status}: ${response.statusText}
- Artifact not found: {path}
- Scheduled task is currently running; retry after the active
- Branching is only available in the main conversation.
AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14).
Data as JSON: /api/errors/f13beef9b5ed3c6d.
Report an issue: GitHub.