langchain-ai/deepagents · error · ValueError

`mode` must be one of 'thread', 'turn', or 'call'.

Error message

`mode` must be one of 'thread', 'turn', or 'call'.

What it means

The snapshot/middleware `mode` option controls snapshot granularity and must be exactly one of `'thread'`, `'turn'`, or `'call'`. `_resolve_mode` normalizes/validates the value at middleware construction and raises `ValueError` for any other string.

Source

Thrown at libs/partners/quickjs/langchain_quickjs/middleware.py:102

        ),
    )


def _resolve_mode(
    *,
    mode: str | None,
) -> PersistenceMode:
    """Normalize persistence mode and enforce invariant constraints."""
    match mode:
        case None | "thread":
            return "thread"
        case "turn":
            return "turn"
        case "call":
            return "call"
        case _:
            msg = "`mode` must be one of 'thread', 'turn', or 'call'."
            raise ValueError(msg)


def _resolve_thread_id(fallback: str) -> str:
    """Extract `thread_id` from langgraph config or use `fallback`.

    The fallback is a middleware-instance-scoped id: when the caller
    didn't configure a `thread_id` (common for ad-hoc
    `agent.invoke(...)` in tests or single-shot scripts), we still need
    all resolver calls within one CodeInterpreterMiddleware lifetime to return the
    same id — otherwise `wrap_model_call` installs tools on one REPL
    and the eval tool looks up a different one, and the model sees
    `ReferenceError: tools is not defined`.
    """
    try:
        config = get_config()
    except RuntimeError:
        # Not running inside a Runnable — test / bare-call path.
        return fallback

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Set `mode` to exactly `'thread'`, `'turn'`, or `'call'` (lowercase).
  2. Validate configuration values before constructing the middleware.
  3. Use a Literal-typed enum/constants in your config layer to catch typos early.

Example fix

// before
QuickJsMiddleware(mode="session")

// after
QuickJsMiddleware(mode="thread")
Defensive patterns

Strategy: validation

Validate before calling

VALID_MODES = {"thread", "turn", "call"}
if mode not in VALID_MODES:
    raise ValueError(f"mode must be one of {sorted(VALID_MODES)}, got {mode!r}")

Type guard

def is_valid_mode(mode) -> bool:
    return isinstance(mode, str) and mode in {"thread", "turn", "call"}

Try / catch

try:
    mw = QuickJsMiddleware(mode=cfg["mode"])
except ValueError as e:
    if "`mode`" in str(e):
        mw = QuickJsMiddleware(mode="thread")  # safe default

Prevention

When it happens

Trigger: Constructing the middleware (whose `__init__` calls `_resolve_mode`) with `mode="session"`, `mode="Thread"` (wrong case), a misspelled value like `"turns"`, or a non-string value.

Common situations: Typos in configuration files or YAML-driven setup; assuming different casing or synonyms ('session', 'request', 'run'); copying an option from another middleware that uses different mode names.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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