langchain-ai/deepagents · error · ValueError
call_id and failed_attempt must be provided together
Error message
call_id and failed_attempt must be provided together
What it means
build_retry_event constructs a model_retry event dict and supports optional retry-correlation fields: call_id and failed_attempt. These two fields are only meaningful as a pair, so providing exactly one raises ValueError('call_id and failed_attempt must be provided together'). This guarantees every retry event either carries the full legacy shape or complete correlation data for downstream matching.
Source
Thrown at libs/code/deepagents_code/model_retry.py:919
attempt: The 1-indexed retry number about to be attempted.
max_retries: The configured maximum retry count.
call_id: Opaque ID correlating every attempt of one model call. Omit
for producers that predate attempt lifecycle events.
failed_attempt: The 0-indexed attempt being superseded. Required to
carry `call_id`.
output_may_have_started: Whether the superseded attempt may have put
message output beyond server control. Conservative by design: the
tracker flags before forwarding a chunk.
Returns:
A stream-writer payload consumed by the client renderers.
Raises:
ValueError: If only one of `call_id` and `failed_attempt` is given.
"""
if (call_id is None) != (failed_attempt is None):
msg = "call_id and failed_attempt must be provided together"
raise ValueError(msg)
event: dict[str, object] = {
"type": "model_retry",
"attempt": attempt,
"max_retries": max_retries,
"message": format_retry_status(attempt, max_retries),
}
if call_id is not None:
event["call_id"] = call_id
event["failed_attempt"] = failed_attempt
event["output_may_have_started"] = output_may_have_started
return event
def build_attempt_event(call_id: str, attempt: int, *, phase: str) -> dict[str, object]:
"""Build the custom-stream payload marking one model attempt boundary.
Args:
call_id: Opaque ID shared by every attempt of one model call.View on GitHub (pinned to a1af029e6e)
Solutions
- Pass both call_id and failed_attempt together (or neither) when building the event.
- If the call_id is unknown, omit both fields to emit the legacy-shape event instead of a partial one.
- Fix call sites/test fixtures to source both values from the same retry attempt record.
Example fix
// before build_retry_event(attempt=2, max_retries=3, call_id="call-1") # ValueError // after build_retry_event(attempt=2, max_retries=3, call_id="call-1", failed_attempt=2)
Defensive patterns
Strategy: validation
Validate before calling
if (call_id is None) != (failed_attempt is None):
raise SystemExit("Pass call_id and failed_attempt together, or neither") Try / catch
try:
event = build_retry_event(attempt, max_retries, call_id=call_id, failed_attempt=failed_attempt)
except ValueError:
event = build_retry_event(attempt, max_retries) # legacy shape Prevention
- Type call_id/failed_attempt as a paired tuple or a single optional correlation object in your code.
- When updating call sites for new fields, grep all build_retry_event callers and update fixtures together.
- Add a unit test asserting partial-correlation inputs are rejected.
When it happens
Trigger: Calling build_retry_event(attempt, max_retries, call_id="abc") without failed_attempt, or failed_attempt=2 without call_id — the XOR check `(call_id is None) != (failed_attempt is None)` fires.
Common situations: Refactoring code that started passing call_id but not the new failed_attempt parameter (or vice versa); constructing the event from partially available data when a call hasn't been assigned an ID yet; test fixtures updated incompletely.
Related errors
- phase must be one of {sorted(_ATTEMPT_PHASES)}, got {phase!r
- modes can only be provided when agent is a factory
- models can only be provided when agent is a factory
- -32602
- recursion_limit must be None or a positive integer
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/d35ba72c5b1cbd04.
Report an issue: GitHub.