Skip to content

[Bug]: Switching back to a provider whose conversation is full gets stuck, and the error asks for a /compact that isn't available #22636

Closed

Description

@notkainoa

Summary

Each provider on a thread keeps its own separate conversation. If a provider's conversation fills up, you switch to another provider, and then you switch back, T3 reopens the same full conversation. Every message then fails with "Insufficient context allowance… Compact the target conversation."

For Factory Droid, and other agents added from the ACP registry, T3 has no way to compact, so the thread can't go back to that provider. Running /compact on the provider you switched to doesn't help either, because it shrinks a different conversation.

Switching back should always work, even if T3 has to give that provider a fresh start.

flowchart LR
  F1["Factory conversation<br/>(full)"] -->|switch| C["Codex conversation"]
  C -->|"/compact<br/>(only shrinks Codex)"| C
  C -->|switch back| F2["Same full Factory conversation<br/>❌ Insufficient context allowance"]
Loading

Area

apps/server

Steps to reproduce

  1. Start a thread on Factory Droid (ACP registry) and work until it has a lot of history. Large command output gets you there faster.
  2. Switch the thread to Codex and send a message. It works.
  3. Run /compact on Codex.
  4. Switch back to Factory Droid and send a message.

Expected behavior

The message goes through. If Factory's old conversation has no room left, T3 handles it without the user doing anything.

Actual behavior

The message fails right away, before Factory receives anything:

Insufficient context allowance for the provider handoff. Compact the target conversation or use a larger-context model; the current request has not been truncated.

Every retry fails the same way. The only ways out are to stay on another provider or to fork the thread.

Impact

Blocks work completely

Version or commit

T3 Code Nightly 0.0.46-nightly.20261014.3132. Code references are to main @ e64766c.

Environment

macOS arm64, Factory Droid 0.228.0 via the ACP registry, Codex

Workaround

Fork the thread, or start a new one, with Factory Droid selected. Factory then gets a fresh conversation plus T3's trimmed summary of the history.


Details

Why compacting the other provider doesn't help. T3 keeps one native session per provider thread. On a switch back, ProviderTurnStartService resumes the target's existing native session, and handoffBudget() subtracts that session's usage from the room available. /compact on Codex only changes Codex's session.

Why the turn fails instead of recovering. deliverContextHandoffs (ContextHandoffDelivery.ts) throws ContextHandoffBudgetError when not even the short coverage note fits, which means the budget is about 0. Nothing catches that error, so the turn fails before the adapter is called. Today, T3 only starts a replacement native session on the resume_failed and uncertain_history_delivery paths (ProviderTurnStartService.ts, around line 707). A full target never takes those paths.

Why the advice in the error doesn't apply here. "Compact the target conversation" needs compactThread. Among ACP flavors, only Grok and Antigravity set supportsCompaction (and #22205 questions Antigravity's). ACP registry agents don't, so for them the suggested fix doesn't exist (see #16663).

Related

Possible directions. These are ideas, not a spec:

  • Treat "resumed session has no room" like resume_failed: start a new native session and deliver the normal trimmed handoff with its t3_thread_read pointer. The trade-off is that the provider loses its native memory of the earlier conversation.
  • If the target supports compaction, compact it first and then deliver.
  • Let the user choose, for example "Start a fresh Factory session", "Compact and retry", or "Send without catching up".
  • At minimum, make the error specific: name the provider, and when compaction isn't available, say what does work (forking, a fresh session).

Activity

  1. ahmetmelihafsar commented on Oct 21, 2026

    @ahmetmelihafsar

    Same thing with Claude Code as the target provider (claudeAgent). T3 Code 0.1.2-nightly.20261021.3457, Linux, Claude Code 2.1.306, Codex CLI 0.163.0.

    I had a long thread on Claude, switched to a second Claude provider instance, then to Codex for many turns, then back to the original Claude instance. Every message failed right away with the same error (3 retries). The handoff was already trimmed to 14 intact items with ~450 omitted, so the summary itself was small. The resumed Claude session had no room left. Running /compact while on Codex didn't help, as the issue says.

    Forking the thread (latest stable) with Claude selected worked immediately: a fresh session plus the trimmed handoff, and the agent had the right context. So treating "resumed session has no room" like resume_failed would have fixed this case too.

    I didn't try /compact with Claude selected, so I can't say whether compacting on the target side would have recovered it.

  2. added
    needs more infoInitial triage showed no bug. Awaiting more info
    and removed
    needs more infoInitial triage showed no bug. Awaiting more info
    on Oct 22, 2026
  3. yonikremer commented on Oct 24, 2026

    @yonikremer

    I have the same bug using grok 4.7 in cursor. I went offline mid session, and restarted my laptop. and then had this error message: Insufficient context allowance for the provider handoff. Compact the target conversation or use a larger-context model; the current request has not been truncated.

  4. TinBane commented on Oct 24, 2026

    @TinBane
    Contributor

    A real Kiro switch-back shows why this needs a fresh-session fallback even after #19414.

    Observed setup: T3 Code with Kiro PR #14693 at 46fe2a1, Kiro CLI 2.33.1, claude-opus-5.5. A long Kiro conversation switched to Claude for several turns, then switched back to Kiro.

    Actual: T3 successfully reloaded Kiro's existing native session, chose delta_since_target_last_seen, then failed before session/prompt with “Insufficient context allowance.” Kiro's own session/load metadata reported that session at 29.52% used, with an 80% summarization threshold and 95% truncation threshold; Opus 5.5 has a 1M context window. T3 nevertheless had no stored contextUsage or known model window for Kiro, so its handoff calculation used the 128k fallback and the one-byte-per-token native-history estimate. The allowance therefore worked out to zero even though the target session had substantial real headroom.

    Relevant current-main paths:

    #19414 prevents the immediate error by deferring a handoff that does not fit. That unwedges the turn, but in this provider-switch case it would send the user's prompt without the intervening provider's turns or even a retrieval pointer. The target has no way to know it missed context.

    Suggested behavior: if a resumed target cannot fit the minimum retrieval pointer, treat it like resume_failed: create a fresh native session and deliver a bounded full_thread_summary. A fresh session has a zero native-context estimate, so the summary fits under the same conservative fallback. If the provider reports reliable usage with room remaining, preserve today's native-session reuse and delta handoff.

    Acceptance criteria

    • A→B→A with no target usage/window and more than ~96 KB of stored native history completes by replacing A's native session and delivering a bounded full summary.
    • A target reporting enough real headroom keeps its native session and receives the delta.
    • A cross-provider handoff is never silently deferred without at least a retrieval pointer reaching the target.
    • Add provider-switch integration coverage for both cases.

    Kiro's missing context metadata mapping is being followed up on #14693. The general fallback remains necessary for providers that cannot report usage or compact.

  5. luquibu commented on Oct 25, 2026

    @luquibu

    Related switch-back case with Codex as the target: T3's handoff reserve blocks the turn even though the last reported native context is below its window.

    Environment and version

    • Windows x64, build 10.0.26200.
    • The local desktop-managed server reports 0.1.2; the affected desktop build and connection mode have not been separately confirmed. Screenshots show the desktop app.
    • Diagnosis source: v0.1.2, commit 044f072.
    • Triage CLI: 0.1.2-nightly.20261022.3541, distinct from the app/server version.

    What happened

    A long thread previously used Codex, then Claude. Returning to Codex failed four times with ContextHandoffBudgetError, using both gpt-6-astra and gpt-6.1-sol. Compacting Claude between attempts did not help. Returning to Claude worked.

    Recorded sequence

    Read-only database projections show the following on 2026-10-25, UTC:

    • 15:47:39: Codex / gpt-6-astra rejected before a native provider turn was created.
    • 15:47:57: Codex / gpt-6.1-sol rejected.
    • 15:49:32: Claude compaction completed, from 153,684 to 17,274 tokens.
    • 15:49:39: Codex / gpt-6.1-sol rejected again.
    • 15:50:12: Codex / gpt-6-astra rejected again.
    • 15:50:26 to 15:54:19: a subsequent Claude run completed.

    Diagnosis and verification

    Codex retained its own native session. Its last accepted root usage report, from 00:24:11 UTC, recorded 388,944 used tokens / 475,000 maximum tokens. The failed attempts did not update that measurement. Claude's compaction affected a separate native conversation.

    T3 reserves max(16,000, window / 4) for the handoff calculation. That reserve was 118,750 tokens, exceeding the 86,056 tokens of remaining reported capacity. Including the current prompt's 30 bytes under T3's accounting:

    475,000 - 388,944 - 30 - 118,750 = -32,724
    handoff budget = 0
    

    A local replay using v0.1.2's pure budget/selection functions and the recorded usage and prompts reproduced zero allowance for all four attempts. Increasing only the imported-history cap still returned zero. Reducing only the target occupancy restored an allowance. This verified the budget calculation; it was not an end-to-end provider reproduction.

    Relevant code: budget calculation, target usage selection, handoff rejection.

    Recovery and relation to this issue

    Unlike the original ACP case, Codex supports compaction. Running /compact with Codex selected remains untested in this triage; compacting Claude did not recover the switch. No live state was changed during diagnosis.

    This adds evidence for the separate-target-session problem, with real usage telemetry and a reserve-triggered rejection. The error would be clearer if it named the target provider and showed used, maximum, and reserved tokens, with recovery directed at that provider.

    Prepared by GPT-6-Astra through Codex, following the T3 Code triage playbook.

  6. TinBane commented on Oct 25, 2026

    @TinBane
    Contributor

    #24579 targets this case. When the resumed target session's reported usage already leaves no room for the handoff, it no longer fails the turn. It starts a fresh native thread with the full portable handoff, provided that payload fits the model's window, and keeps the old session otherwise. Its provider-switch tests cover a known-window overflow like your Codex numbers, but I haven't replayed your recorded state against it.

    The clearer error you suggest (naming the target provider, with used, maximum and reserved tokens) isn't in that PR.

  7. juliusmarminge commented on Oct 30, 2026

    @juliusmarminge
    Member

    Closing: current main already covers this as of 07242abff3. If you still see it on a build that includes that commit, reply and we'll reopen.

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