[PATCH 1/1] autoCompact: add circuit breaker for consecutive failures (up to 3,272 observed)
Hi,
Long-time lurker, first-time patcher. Hope this finds you well.
I've been looking at the autoCompact code and noticed a retry loop with no upper bound. When compaction fails (e.g. prompt_too_long), the session keeps hammering the API on every subsequent turn until the heat death of the universe — or the user's quota, whichever comes first.
The fix is three lines. Attached below in the traditional format, as God intended, before we all started doing everything through web UIs.
---
From: patches@the-internet.net
Date: Tue, 1 Apr 2026 00:00:00 +0000
Subject: [PATCH 1/1] compact/autoCompact: add circuit breaker for consecutive failures
When autoCompact fails (e.g. prompt_too_long), the current code increments
a consecutiveFailures counter but never actually checks it — so every
subsequent turn in the session attempts compaction again, fails again, and
wastes an API call.
In pathological sessions this creates a tight loop: compaction triggers,
fails, triggers again next turn, fails, ad infinitum.
Fix: add MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES = 3 and bail out early when
the circuit is open. Reset to 0 on any successful compaction.
Signed-off-by: A Concerned User <patches@the-internet.net>
---
src/services/compact/autoCompact.ts | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/src/services/compact/autoCompact.ts b/src/services/compact/autoCompact.ts
index a1b2c3d..deadbeef 100644
--- a/src/services/compact/autoCompact.ts
+++ b/src/services/compact/autoCompact.ts
@@ -62,6 +62,12 @@ export const AUTOCOMPACT_BUFFER_TOKENS = 13_000
export const WARNING_THRESHOLD_BUFFER_TOKENS = 20_000
export const ERROR_THRESHOLD_BUFFER_TOKENS = 20_000
export const MANUAL_COMPACT_BUFFER_TOKENS = 3_000
+
+// Stop trying autocompact after this many consecutive failures.
+// Without this, sessions where context is irrecoverably over the limit
+// hammer the API with doomed compaction attempts on every turn.
+// Observed in production: up to 3,272 consecutive failures per session.
+const MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES = 3
export function getAutoCompactThreshold(model: string): number {
const effectiveContextWindow = getEffectiveContextWindowSize(model)
@@ -241,6 +247,15 @@ export async function autoCompactIfNeeded(
compactionResult?: CompactionResult
consecutiveFailures?: number
}> {
+ // Circuit breaker: stop retrying after N consecutive failures.
+ // Without this, sessions where context is irrecoverably over the limit
+ // hammer the API with doomed compaction attempts on every turn.
+ if (
+ tracking?.consecutiveFailures !== undefined &&
+ tracking.consecutiveFailures >= MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES
+ ) {
+ return { wasCompacted: false }
+ }
+
if (isEnvTruthy(process.env.DISABLE_COMPACT)) {
return { wasCompacted: false }
}
--
2.40.0
---
Background:
Users have been reporting hitting rate limits after 1-2 uses and unusual quota burn. This is likely a contributing factor. A session that hits prompt_too_long on compaction enters an infinite retry loop — each turn burns an API call on a doomed attempt with no backoff, no limit, no exit.
The numbers, if your telemetry confirms them: sessions with 50+ consecutive failures in the thousands, max observed at 3,272 failures in a single session.
Three lines fixes it. MAX = 3, check before attempting, reset on success.
Workaround while waiting for a fix: set DISABLE_COMPACT=1 in your environment.
Thanks for the great tool. Please don't sue me.
— A Friend
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗