langchain-ai/deepagents · warning · ClientHookStopError
Compact session start stopped by hook
Error message
Compact session start stopped by hook
What it means
After an automatic context compaction, _after_automatic_compact fires the SessionStart hook with cause COMPACT. If the hook rejects (outcome.ok is false), a ClientHookStopError is raised with the hook's stop_reason or this default, halting the resumed stream because the post-compact session start was vetoed.
Source
Thrown at libs/code/deepagents_code/tui/textual_adapter.py:1872
recover_interrupted_turn = not (
graph_input is not None and graph_input.get("goal_criteria_request") is not None
)
# Track summarization lifecycle so spinner status and notification stay in sync.
summarization_in_progress = False
completed_compaction_ids: set[str] = set()
async def _after_automatic_compact() -> None:
from deepagents_code.config import runtime_state
from deepagents_code.hooks.client_lifecycle import ClientHookStopError
from deepagents_code.hooks.models.domain import SessionStartCause
outcome = await hooks.on_session_start(
SessionStartCause.COMPACT,
model=runtime_state.model_name or None,
)
if not outcome.ok:
raise ClientHookStopError(
outcome.stop_reason or "Compact session start stopped by hook"
)
stream_completed = False
try:
while True:
interrupt_occurred = False
suppress_resumed_output = False
pending_interrupts: dict[str, tuple[tuple[Any, ...], HITLRequest]] = {}
pending_ask_user: dict[str, AskUserRequest] = {}
pending_hook_resumes: dict[str, dict[str, Any]] = {}
if context is None:
context = CLIContext()
context["thread_id"] = thread_id
if turn_id is not None:
context["turn_id"] = turn_id
else:View on GitHub (pinned to a1af029e6e)
Solutions
- Update the session_start hook to accept SessionStartCause.COMPACT.
- Check the hook's stop_reason output to see why it denied the compact restart and adjust policy.
- Handle ClientHookStopError around execute_task_textual to surface the reason gracefully.
- Temporarily disable the session_start hook to unblock the session.
Example fix
// before
# hook: only allow startup
if cause != "startup": return deny("unsupported cause")
// after
if cause not in ("startup", "resume", "compact"):
return deny("unsupported cause") Defensive patterns
Strategy: try-catch
Validate before calling
if hooks.has_handlers(HookEvent.SESSION_START):
probe = await hooks.on_session_start(SessionStartCause.COMPACT, model=model)
if not probe.ok:
disable_compaction_hooks() Try / catch
try:
await execute_task_textual(adapter, user_input)
except ClientHookStopError as exc:
logger.warning("post-compact session start denied: %s", exc)
recover_session() Prevention
- Ensure session_start hooks accept all SessionStartCause values, including COMPACT.
- Exercise compaction in integration tests when hooks are installed.
- Keep hook scripts fast and non-failing for lifecycle events.
When it happens
Trigger: Automatic compaction triggers mid-conversation and the registered session_start hook returns ok=false for the COMPACT cause — the turn aborts right after compaction.
Common situations: Session-start hooks that only permit 'startup'/'resume' causes but not 'compact'; a hook script erroring on the compact payload; policy hooks that deny session starts in certain states.
Related errors
- Compact session start stopped by hook
- Session start stopped by hook
- User prompt submission stopped by hook
- Server process is not running
- A workspace is required to start the remote agent.
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/bb6dfb748237710d.
Report an issue: GitHub.