siyuan-note/siyuan · error

errContextCannotBeCompacted

errContextCannotBeCompacted

Error message

%w: model context length is unknown

What it means

The agent's context compaction routine wraps errContextCannotBeCompacted and reports that the model's context length is unknown (contextLimit <= 0), so it cannot compute an input budget or decide what to compact. When force is false it silently skips compaction; when force is true it must fail loudly because compaction is impossible.

Solutions

  1. Configure the model's context length explicitly (model config/metadata) so contextLimit > 0
  2. Use a model name the provider registry recognizes so its context window can be resolved
  3. Update model metadata/config if the provider recently renamed or added the model
  4. If compaction was auto-forced after a context error, verify the endpoint reports token usage/limits correctly

Example fix

// before: unknown context size for custom model
model := "my-finetune-v2" // no context length known
// after: declare the context window in the model config
modelCfg.ContextLength = 128000
Defensive patterns

Strategy: validation

Validate before calling

if model.ContextLength <= 0 {
    return fmt.Errorf("model %q has no configured context length; set it before enabling forced compaction", model.Name)
}

Type guard

func hasKnownContext(limit int) bool { return limit > 0 }

Try / catch

if err := agent.Compact(ctx, true); err != nil {
    if errors.Is(err, errContextCannotBeCompacted) && strings.Contains(err.Error(), "context length is unknown") {
        // configure model context length and retry, or skip compaction
    }
}

Prevention

When it happens

Trigger: compactContext(requestTools, force=true) runs while contextLimit <= 0 — i.e. the model metadata lookup returned no context window (unknown/0/missing model info) and compaction was explicitly requested (e.g. after a context-length API error or manual compaction).

Common situations: Using a model whose context size is not in the provider/model registry or config; a custom OpenAI-compatible endpoint that omits context_length; renamed model IDs the size table does not recognize.

Understand the failure class

Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/56e83485df579413. Report an issue: GitHub.

Appendix: source

Thrown at kernel/agent/agent.go:767

			if imageInputDisabled {
				return downgradeImageInput(source)
			}
			return source, false
		}
		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)

View on GitHub (pinned to 9f775e8a12)