langchain-ai/deepagents · error · RuntimeError

Manual approval mode could not be persisted; graph…

Error message

Manual approval mode could not be persisted; graph execution is blocked until the Store is available.

What it means

When persisting the approval mode fails, the adapter falls back to MANUAL (in-memory) and notifies the UI, but because graph execution cannot safely continue without durable approval state, it re-raises the original failure as RuntimeError with this message. This prevents executing with an approval mode that could silently differ from what the user selected.

Solutions

  1. Restore Store connectivity (check network/credentials/backend health) and retry the turn.
  2. Restart the session so the Store writer is re-established before continuing.
  3. If persistence is repeatedly unavailable, run without auto-approve (Manual mode) via a config that does not require Store persistence.
  4. Wrap the persistence call to surface a retry dialog instead of killing graph execution.

Example fix

// before
persist_approval_mode(adapter, mode)  # raises on Store outage
// after
try:
    persist_approval_mode(adapter, mode)
except StoreUnavailable:
    adapter._update_status("Store offline; staying in Manual approval mode")
    mode = ApprovalMode.MANUAL
Defensive patterns

Strategy: try-catch

Validate before calling

if not store_health_check(adapter):
    adapter._update_status("Store offline; forcing Manual approval mode")
    session_state.approval_mode = ApprovalMode.MANUAL
else:
    persist_approval_mode(adapter, selected_mode)

Try / catch

try:
    persist_approval_mode(adapter, selected_mode)
except RuntimeError as exc:
    logger.error("approval persistence failed, staying Manual: %s", exc)
    selected_mode = ApprovalMode.MANUAL

Prevention

When it happens

Trigger: During execute_task_textual, writing the selected approval mode to the Store raises (Store unavailable, connection error, backend exception); the fallback to MANUAL succeeds in memory but persistence still fails, so the turn is blocked.

Common situations: Remote agent Store outage mid-session; network partition to the persistence backend; expired credentials for the Store; running a session whose Store writer was never initialized.

Related errors


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

Appendix: source

Thrown at libs/code/deepagents_code/tui/textual_adapter.py:1939

                            agent,
                            thread_id,
                            mode=ApprovalMode.MANUAL,
                        )
                    )
                except Exception as exc:
                    context["approval_mode"] = ApprovalMode.MANUAL.value
                    context["auto_approve"] = False
                    context.pop("approval_mode_key", None)
                    session_state.approval_mode = ApprovalMode.MANUAL
                    session_state.approval_mode_key = None
                    if adapter._on_approval_mode_fallback is not None:
                        adapter._on_approval_mode_fallback(ApprovalMode.MANUAL.value)
                    adapter._update_status("Approval mode fell back to Manual")
                    msg = (
                        "Manual approval mode could not be persisted; graph execution "
                        "is blocked until the Store is available."
                    )
                    raise RuntimeError(msg) from exc
                selected_mode = ApprovalMode.MANUAL
                session_state.approval_mode = ApprovalMode.MANUAL
                context["approval_mode"] = ApprovalMode.MANUAL.value
                context["auto_approve"] = False
                if adapter._on_approval_mode_fallback is not None:
                    adapter._on_approval_mode_fallback(ApprovalMode.MANUAL.value)
                adapter._update_status("Approval mode fell back to Manual")
            context["approval_mode_key"] = live_key
            session_state.approval_mode_key = live_key

            from deepagents_code.hooks.interrupt import is_hook_interrupt_payload
            from deepagents_code.hooks.models.domain import HookEvent

            hooks.apply_graph_context(context)

            # Show the Thinking spinner before each astream iteration so
            # both the first turn and HITL/ask_user resumes surface feedback
            # while the model processes input. Skip when

View on GitHub (pinned to a1af029e6e)