bytedance/deer-flow · warning · HTTPException
Could not locate target user message in recent checkpoint hi
Error message
Could not locate target user message in recent checkpoint history (limit={REGENERATE_HISTORY_SCAN_LIMIT}) What it means
Raised in _find_base_checkpoint_before_human (HTTP 409) when the target user message id cannot be located anywhere in the scanned checkpoint history (bounded by REGENERATE_HISTORY_SCAN_LIMIT = 200 non-duration-only checkpoints). The chronological fallback could not even find the message, so no base checkpoint can be chosen.
Source
Thrown at backend/app/gateway/routers/thread_runs.py:572
raise HTTPException(status_code=500, detail="Failed to inspect checkpoint history") from exc
previous_checkpoint, target_found = find_checkpoint_before_message_chronologically(raw_checkpoints, human_message_id)
if target_found:
if previous_checkpoint is None:
raise HTTPException(
status_code=409,
detail=_MISSING_REGENERATE_BASE_DETAIL,
)
return previous_checkpoint
if len(checkpoints) >= REGENERATE_HISTORY_SCAN_LIMIT:
logger.warning(
"Could not locate target user message %s in recent checkpoint history for thread %s (limit=%s)",
human_message_id,
thread_id,
REGENERATE_HISTORY_SCAN_LIMIT,
)
raise HTTPException(
status_code=409,
detail=(f"Could not locate target user message in recent checkpoint history (limit={REGENERATE_HISTORY_SCAN_LIMIT})"),
)
def _run_status_value(record: Any) -> str | None:
status = getattr(record, "status", None)
if isinstance(status, RunStatus):
return status.value
return str(status) if status is not None else None
async def _require_successful_source_run(thread_id: str, run_id: str, request: Request) -> RunRecord:
run_mgr = get_run_manager(request)
user_id = await get_current_user(request)
record = await run_mgr.get(run_id, user_id=user_id)
if record is None:
# The run-event journal is the authoritative lookup above. This fallbackView on GitHub (pinned to 1dd6ba1acb)
Solutions
- Regenerate the latest turn instead of an old one that fell outside the 200-checkpoint window.
- Verify the message id exists in the thread's checkpointed state (GET thread state and search messages).
- If long threads are the norm, raise REGENERATE_HISTORY_SCAN_LIMIT in the backend and restart the Gateway.
- For messages that never checkpointed (aborted turns), resend the user message as a new run.
Defensive patterns
Strategy: fallback
Validate before calling
const state = await getThreadState(threadId);
const hasMsg = state.messages.some(m => m.id === humanMessageId);
if (!hasMsg) { /* id stale or beyond history; refresh */ } Try / catch
try { await regeneratePrepare(threadId, messageId); } catch (e) { if (e.status === 409 && /recent checkpoint history/.test(e.detail)) { await refreshAndRegenerateLatest(threadId); } else throw e; } Prevention
- Regenerate only the latest turn in long threads
- Keep REGENERATE_HISTORY_SCAN_LIMIT aligned with thread depth
- Refresh ids from thread state before calling
When it happens
Trigger: Regenerating a message older than the 200-checkpoint scan window; the human message never reached a checkpoint (interrupted before first checkpoint write); message id that exists only in the live stream, not in any checkpointed state.
Common situations: Very long threads (each graph step writes a checkpoint, so 200 covers few turns); regenerate targeting a message whose turn was aborted pre-checkpoint; stale client id.
Related errors
- Checkpoint is missing checkpoint_id
- Could not safely resolve the checkpoint before the target us
- Could not find an addressable checkpoint before the target u
- Only the latest completed user turn can be edited
- Only completed assistant text turns can be edited
AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14).
Data as JSON: /api/errors/62a2cdccec4e911e.
Report an issue: GitHub.