Skip to content

[Bug]: Claude request and compaction phases can remain stuck indefinitely #24842

Open

Description

@connwalk

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/server

Steps to reproduce

This was observed in several long-running native Claude Agent threads near the model context limit:

  1. Continue a large Claude thread until Claude starts automatic context compaction, or until a provider request enters its retry/requesting phase.
  2. Observe the native SDK stream repeatedly emit the same system/status: compacting, system/status: requesting, or system/api_retry state without a model, tool, result, or terminal frame.
  3. Try to stop the turn or send later work.

In one incident, status: compacting arrived every 30 seconds for about 26 minutes with no other progress. Other affected runs ended only after a provider disconnect or manual interruption.

Expected behavior

A provider phase that produces no model or tool progress for a bounded period should fail visibly, release the active turn, and ensure the next attempt uses a fresh native Claude session with a portable history handoff.

Stopping a turn should also finish even when the native SDK's interrupt or close request never resolves.

Actual behavior

Repeated status frames keep the Claude query and T3 turn alive indefinitely. The active turn retains query ownership, later work remains blocked, and retrying the same native session can return to the same bad state.

The adapter has bounds around some provider setup operations, but the request/compaction phases themselves have no progress deadline. A close or interrupt call can also wait indefinitely.

Impact

Blocks work completely.

Several active development threads had to be interrupted and recreated. Long threads are more likely to enter the affected compaction path.

Version or commit

Reproduced before main commit 056b4457cc; source diagnosis and proposed fix are rebased onto that commit.

Environment

  • macOS, Apple Silicon
  • T3 Code desktop/local server
  • Native Claude Agent SDK provider
  • Claude Opus 5.5
  • Long-lived conversations near the provider context limit

Logs or stack traces

system/status compacting
... 30 seconds ...
system/status compacting
... repeated for approximately 26 minutes ...
(no assistant, tool, result, or terminal frame)

The affected request carried roughly 469k input-context tokens. Prompt-cache reads were present, but cache reuse does not reduce the logical conversation size or complete a stalled compaction.

Cause

ClaudeAdapterV2 treats each SDK frame as activity but does not distinguish repeated phase-status heartbeats from model/tool progress. It has no deadline for an unchanged requesting, api_retry, or compacting phase.

If the process is interrupted, the persisted provider thread still points at the same native session, so the next run can resume that bad session instead of taking the existing fresh-session/full-summary fallback.

Proposed fix

  • Bound Claude interrupt and query-close requests.
  • Track the current request/compaction phase per active turn.
  • Do not reset its deadline for repeated copies of the same status.
  • After two minutes with no model/tool progress, terminalize the turn with a typed, retryable native_session_stalled failure.
  • Persist enough identity to associate that failure with the exact provider attempt and native session.
  • On the next run, use the existing resume-fallback path to allocate a fresh native Claude session and deliver a full_thread_summary handoff.

A pull request with focused adapter and recovery tests will follow.

Related

Workaround

Interrupt the affected run and start a fresh Claude thread with a summary of the prior thread. Resuming the poisoned native Claude session is unreliable.


Model: GPT-5.6, Codex harness.

Activity

  1. paul-cch commented on Nov 3, 2026

    @paul-cch

    We see the same no-signal behaviour on a self-hosted server, and not only with Claude:

    A per-provider deadline as proposed here, and in #17503 for Codex, would help. A small cross-provider addition would cover the cases those miss: if a running turn has produced no new item for N minutes (15, say), mark it on the turn ("No output for 15 min") and flag the thread in the inbox, with Stop and Retry next to it. That doesn't require T3 to decide whether the provider is really stuck. It just stops the user from finding out by poking the thread.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions