langchain-ai/deepagents · error · ValueError

{key} must be a positive integer

Error message

{key} must be a positive integer

What it means

_positive_int_from_env reads an environment variable (used by _context_size_from_env and _recursion_limit_from_env) and raises this ValueError when its value is not parseable as an int or parses to <= 0. It exists so misconfigured env values fail fast at startup with a clear message naming the offending key.

Source

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

    """Resolve the recursion limit from the environment with a code fallback.

    The `DEEPAGENTS_TALON_RECURSION_LIMIT` env var, when set, overrides the
    caller-supplied value so operators can tune the graph recursion limit
    without changing code. Falls back to the caller value when unset.
    """
    resolved = _positive_int_from_env(env, RECURSION_LIMIT_ENV_KEY)
    return resolved if resolved is not None else fallback


def _positive_int_from_env(env: Mapping[str, str], key: str) -> int | None:
    raw = env.get(key)
    if raw is None or not raw.strip():
        return None
    try:
        value = int(raw)
    except ValueError as exc:
        msg = f"{key} must be a positive integer"
        raise ValueError(msg) from exc
    if value <= 0:
        msg = f"{key} must be a positive integer"
        raise ValueError(msg)
    return value


def _has_summarization_tool_middleware(
    middleware: Sequence[AgentMiddleware[Any, Any, Any]],
) -> bool:
    return any(isinstance(item, SummarizationToolMiddleware) for item in middleware)


def _apply_context_size(model: BaseChatModel, context_size: int) -> None:
    profile = getattr(model, "profile", None)
    merged = (
        {**profile, "max_input_tokens": context_size}
        if isinstance(profile, dict)
        else {"max_input_tokens": context_size}

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Set the env variable to a positive integer string (e.g. `export AGENT_RECURSION_LIMIT=50`)
  2. Remove/unset the variable to fall back to the built-in default
  3. Fix template substitution so placeholders like `${VAR}` are replaced before the process starts

Example fix

// before
AGENT_CONTEXT_SIZE=25.5
// after
AGENT_CONTEXT_SIZE=128000
Defensive patterns

Strategy: validation

Validate before calling

import os, re

_INT_RE = re.compile(r"^[1-9][0-9]*$")

def require_positive_env(key: str) -> int | None:
    raw = os.environ.get(key)
    if raw is None or not raw.strip():
        return None
    if not _INT_RE.match(raw.strip()):
        raise ValueError(f"{key} must be a positive integer, got {raw!r}")
    return int(raw)

require_positive_env("AGENT_RECURSION_LIMIT")
require_positive_env("AGENT_CONTEXT_SIZE")

Type guard

def is_positive_int_str(raw: str) -> bool:
    try:
        return int(raw) > 0
    except (TypeError, ValueError):
        return False

Prevention

When it happens

Trigger: Setting the relevant env variable (context size or recursion limit) to a non-integer string like "25.5", "default", "", whitespace with junk, or to 0 / a negative integer.

Common situations: Docker/compose files quoting values oddly; putting a float where an int is required; secrets manager injecting an unset placeholder like "${VAR}"; operators setting 0 expecting 'disabled/unlimited'.

Related errors


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