langchain-ai/deepagents · error · ValueError

max_retries must be at least 1

Error message

max_retries must be at least 1

What it means

DeepAgentRuntime.__init__ requires max_retries to be at least 1 and raises this ValueError otherwise. The retry loop in _invoke_payload_with_retries is written assuming at least one attempt, so 0 or negative values are rejected up front.

Source

Thrown at libs/talon/deepagents_talon/runtime.py:257

        middleware: Sequence[AgentMiddleware[Any, Any, Any]] = (),
        interrupt_on: Mapping[str, bool | InterruptOnConfig] | None = None,
        memory: Sequence[str] | None = None,
        checkpointer: Checkpointer | None = None,
        include_web_tools: bool = True,
        recursion_limit: int = DEFAULT_RECURSION_LIMIT,
        max_retries: int = DEFAULT_MAX_RETRIES,
        max_continuations: int = DEFAULT_MAX_CONTINUATIONS,
        env: Mapping[str, str] | None = None,
    ) -> None:
        """Initialize without constructing the graph."""
        values = os.environ if env is None else env
        resolved_recursion_limit = _recursion_limit_from_env(values, recursion_limit)
        if resolved_recursion_limit <= 0:
            msg = "recursion_limit must be positive"
            raise ValueError(msg)
        if max_retries < 1:
            msg = "max_retries must be at least 1"
            raise ValueError(msg)
        if max_continuations < 0:
            msg = "max_continuations cannot be negative"
            raise ValueError(msg)

        self.model = model
        self.tools = tuple(tools)
        self.system_prompt = system_prompt
        self.subagents = tuple(subagents) if subagents is not None else None
        self._has_async_subagents = _has_async_subagents(self.subagents)
        self.assistant_dir = assistant_dir
        self.cron_store = cron_store
        self.env = dict(os.environ if env is None else env)
        self.backend = backend if backend is not None else _default_backend(self.env)
        self.skills = tuple(skills) if skills is not None else None
        self.middleware = tuple(middleware)
        self.interrupt_on = interrupt_on_with_env_overlay(interrupt_on, self.env)
        self.memory = tuple(memory) if memory is not None else None
        self.checkpointer = checkpointer if checkpointer is not None else InMemorySaver()

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Pass max_retries >= 1 to DeepAgentRuntime
  2. If you want effectively no retries, use max_retries=1 (single attempt)
  3. Clamp computed values before construction: `max_retries=max(1, computed)`

Example fix

// before
runtime = DeepAgentRuntime(..., max_retries=0)
// after
runtime = DeepAgentRuntime(..., max_retries=1)  # 1 = single attempt, no retries
Defensive patterns

Strategy: validation

Validate before calling

def sanitize_retries(n: int) -> int:
    return max(1, int(n))

runtime = DeepAgentRuntime(..., max_retries=sanitize_retries(config.retries))

Type guard

def valid_retries(v: object) -> bool:
    return isinstance(v, int) and not isinstance(v, bool) and v >= 1

Prevention

When it happens

Trigger: Constructing DeepAgentRuntime with max_retries=0 or a negative number.

Common situations: Config that uses 0 to mean 'no retries' (this library means 'at least one attempt'); a computed retry count like `max(0, attempts - 1)` fed straight into the constructor.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/d4663f4eafcfc3c2. Report an issue: GitHub.