sipeed/picoclaw · error

context window still exceeded after retry compaction; refusi

Error message

context window still exceeded after retry compaction; refusing to drop active turn messages: %w

What it means

Thrown in the LLM retry loop (pipeline_llm.go) after a context-compaction rebuild was attempted and the message history STILL does not fit the context budget. The library deliberately refuses to shrink further because that would require dropping messages from the active turn (protectedTurnTail), which would corrupt in-flight conversation state; it wraps the original fit error instead.

Source

Thrown at pkg/agent/pipeline_llm.go:443

					"retry":           retry,
					"dropped_msgs":    dropped,
					"remaining_msgs":  len(exec.history),
					"context_window":  ts.agent.ContextWindow,
					"max_tokens":      ts.agent.MaxTokens,
					"still_overlimit": !fit,
				})
			} else if !fit {
				logger.WarnCF("agent", "Context still exceeds budget after retry compaction rebuild", map[string]any{
					"session_key":         ts.sessionKey,
					"retry":               retry,
					"history_msgs":        len(exec.history),
					"protected_turn_msgs": len(protectedTurnTail),
					"context_window":      ts.agent.ContextWindow,
					"max_tokens":          ts.agent.MaxTokens,
				})
			}
			if !fit {
				err = fmt.Errorf(
					"context window still exceeded after retry compaction; refusing to drop active turn messages: %w",
					err,
				)
				break
			}
			continue
		}
		break
	}

	if err != nil {
		al.emitEvent(
			runtimeevents.KindAgentError,
			ts.eventMeta("runTurn", "turn.error"),
			ErrorPayload{
				Stage:   "llm",
				Message: err.Error(),
			},

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Increase the agent's ContextWindow (or move to a larger-context model) so the active turn + compacted history fits
  2. Reduce the size of current-turn tool outputs: truncate/limit tool results before they enter history
  3. Start a new session or clear history so the compacted baseline is smaller
  4. Verify MaxTokens leaves headroom — it consumes part of the window budget

Example fix

# before
agents:
  defaults:
    model: llama-3-8k-text   # tiny window, huge tool outputs

# after
agents:
  defaults:
    model: gpt-4o            # 128k window
    max_tokens: 4096
Defensive patterns

Strategy: validation

Validate before calling

func estimateTokens(msgs []providers.Message) int {
    n := 0
    for _, m := range msgs {
        n += len(m.Content) / 4 // rough chars-per-token heuristic
    }
    return n
}

// before the turn: refuse to send if the active turn alone cannot fit
if estimateTokens(exec.messages) > ts.agent.ContextWindow-ts.agent.MaxTokens {
    return fmt.Errorf("history too large for window %d; trim tool outputs or widen window", ts.agent.ContextWindow)
}

Type guard

func isContextOverflowError(err error) bool {
    return err != nil && strings.Contains(err.Error(), "context window still exceeded")
}

Try / catch

if err := runTurn(); isContextOverflowError(err) {
    // recover by starting a fresh session or widening the window, then retry
    session.Reset()
    widenContextWindow(agent)
    return runTurn()
}

Prevention

When it happens

Trigger: agent.ContextWindow/MaxTokens too small for: protected active-turn messages (large tool outputs, huge pasted files) + compacted history. Compaction already trimmed what it could (logged via 'Context still exceeds budget after retry compaction rebuild'), the fit check fails again, and the loop aborts with this error.

Common situations: Huge tool results (file reads, command dumps) inside the current turn; a small-window model (7k-8k) assigned to an agent with verbose tools; long sessions whose compacted summary plus turn tail still exceed the window; MaxTokens set close to ContextWindow leaving no room for history.

Related errors


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/e8fb714820b2c36c. Report an issue: GitHub.