langchain-ai/deepagents · error · ValueError

preloaded thread history requires resume_thread_id

Error message

preloaded thread history requires resume_thread_id

What it means

When constructing a remote agent, supplying a preloaded thread-history payload (`preloaded_payload`) without also naming the thread via `resume_thread_id` is ambiguous — there is no thread to attach the history to — so a ValueError is raised in the setup path.

Source

Thrown at libs/code/deepagents_code/app.py:23861

            resume_thread_id: Existing thread to resume under the new agent.
                `None` starts a fresh thread, preserving normal agent-picker
                behavior.
            preloaded_payload: History fetched before a combined agent/thread
                transition mutates the current session.
            persist_default_agent: Whether the switch should become the saved
                default agent. One-off thread resumes leave it unchanged.

        Returns:
            `True` when the new agent is running and the requested transition
            completed, otherwise `False`.

        Raises:
            ValueError: If a preloaded history payload is supplied without a
                thread to resume.
        """
        if preloaded_payload is not None and resume_thread_id is None:
            msg = "preloaded thread history requires resume_thread_id"
            raise ValueError(msg)

        from deepagents_code._env_vars import SERVER_ENV_PREFIX
        from deepagents_code.client.remote_client import RemoteAgent as _RemoteAgent

        def _build_agent(url: str) -> Any:  # noqa: ANN401  # see docstring
            """Build a new `RemoteAgent` typed as `Any`.

            Returns `Any` so `self._agent`'s attribute type stays aligned
            with the permissive type the startup path assigns, avoiding a
            union that would trip call-site type checks on
            `aget_state(config)` et al.

            Args:
                url: Server base URL to point the new client at.

            Returns:
                A fresh `RemoteAgent`, exposed as `Any`.
            """

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Pass resume_thread_id together with preloaded_payload
  2. Persist and reload the thread ID alongside the history payload
  3. If there is no thread to resume, omit preloaded_payload and start a fresh thread

Example fix

// before
build_agent(url, preloaded_payload=history)
// after
build_agent(url, preloaded_payload=history, resume_thread_id=thread_id)
Defensive patterns

Strategy: validation

Validate before calling

if preloaded_payload is not None and resume_thread_id is None:
    raise ValueError("cannot preload history without a thread id to resume")

Type guard

def can_build_remote_agent(preloaded_payload: object, resume_thread_id: str | None) -> bool:
    return preloaded_payload is None or resume_thread_id is not None

Try / catch

try:
    agent = build_remote_agent(url, preloaded_payload=history, resume_thread_id=thread_id)
except ValueError as exc:
    logger.error("session restore failed: %s", exc)
    agent = build_remote_agent(url)  # fresh thread fallback

Prevention

When it happens

Trigger: Calling the remote-agent builder with `preloaded_payload=<history>` but `resume_thread_id=None`, e.g. restoring cached conversation state from disk after losing the thread ID, or passing the payload from one code path and the thread ID from another.

Common situations: Session restore/undo features that persisted history but not the thread ID; mismatched argument plumbing between a UI layer and the agent factory.

Understand the failure class

Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.

Related errors


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