siyuan-note/siyuan · error · errContextCannotBeCompacted

%w: no input budget remains

Error message

%w: no input budget remains

What it means

compactContext computes inputBudget = contextInputBudget(contextLimit, maxCompletionTokens). If the budget is <= 0 — the reserved completion tokens are not smaller than the model's context limit — there is no room for any input, so it returns errContextCannotBeCompacted wrapped with "no input budget remains". Compaction cannot help because even a minimal context would not fit.

Source

Thrown at kernel/agent/agent.go:768

		}
		compactionErrorMessage := func(err error) string {
			if errors.Is(err, errContextCannotBeCompacted) || isContextOverflow(err) {
				return kernelModel.Conf.Language(352)
			}
			requestMessages, _ := projectImageMessages(messages)
			return getAgentRequestErrorMessage(err, requestMessages)
		}

		compactContext := func(requestTools []openai.Tool, force bool) (bool, error) {
			if contextLimit <= 0 {
				if !force {
					return false, nil
				}
				return false, fmt.Errorf("%w: model context length is unknown", errContextCannotBeCompacted)
			}
			inputBudget := contextInputBudget(contextLimit, maxCompletionTokens)
			if inputBudget <= 0 {
				return false, fmt.Errorf("%w: no input budget remains", errContextCannotBeCompacted)
			}
			estimatedMessages, _ := projectImageMessages(messages)
			if !force && estimateProtocolRequestTokens(model, protocol, estimatedMessages, checkpointMsgs,
				compaction, requestTools) <= inputBudget {
				return false, nil
			}

			coveredEntryCount := 0
			previousSummary := ""
			if compaction != nil {
				coveredEntryCount = compaction.CoveredEntryCount
				previousSummary = compaction.Summary
			}
			candidates := compactionCandidateEntryCounts(sessionEntries, coveredEntryCount, userEntryID)
			if len(candidates) == 0 {
				return false, fmt.Errorf("%w: the current turn is too large", errContextCannotBeCompacted)
			}
			tail, ok := currentTurnTail(checkpointMsgs, userEntryID, userMessage)

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Lower the max completion tokens setting so it is well below the model context limit, leaving room for input
  2. Switch to a model with a larger context window
  3. Review contextInputBudget configuration so the budget stays positive

Example fix

// before
maxCompletionTokens = 32768 // with contextLimit = 16384 -> budget <= 0
// after
maxCompletionTokens = 4096 // well below the 16384-token context limit
Defensive patterns

Strategy: validation

Validate before calling

budget := contextInputBudget(contextLimit, maxCompletionTokens)
if budget <= 0 {
    return fmt.Errorf("invalid config: maxCompletionTokens (%d) must be smaller than contextLimit (%d)",
        maxCompletionTokens, contextLimit)
}

Try / catch

if err := agent.Run(ctx, input); errors.Is(err, errContextCannotBeCompacted) &&
    strings.Contains(err.Error(), "no input budget remains") {
    // lower maxCompletionTokens or raise contextLimit, then retry
}

Prevention

When it happens

Trigger: maxCompletionTokens >= contextLimit in the agent configuration, so contextInputBudget yields a non-positive budget. Typically a model with a small context window combined with a large max-completion-token setting.

Common situations: Pointing the agent at a model with a small context (e.g. 4k) while the completion limit is configured at or above that; misconfigured provider defaults where maxCompletionTokens is inherited from a larger model.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/4d813fad503001bf. Report an issue: GitHub.