[PATCH 1/1] autoCompact: add circuit breaker for consecutive failures (up to 3,272 observed)

Resolved 💬 2 comments Opened Apr 1, 2026 by Gonzih Closed May 8, 2026

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

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗