siyuan-note/siyuan · error

response compaction returned no output

Error message

response compaction returned no output

What it means

CompactOpenAIResponse marshals the compaction result's Output array via MarshalOpenAIResponseOutput; when the marshaled output slice is empty, there is nothing to compact into a prompt and the function fails with this error. The API contract expects a compaction to always produce at least one output item.

Source

Thrown at kernel/util/openai_completion.go:154

}

func CompactOpenAIResponse(ctx context.Context, client *openai.Client, request openai.ChatCompletionRequest,
	responseInput []any) ([]json.RawMessage, *openai.ResponseUsage, error) {
	responseRequest := openai.CompactResponseRequest{
		Model:        request.Model,
		Input:        responseInput,
		Instructions: firstSystemMessage(request.Messages),
	}
	compaction, err := client.CompactResponse(ctx, responseRequest)
	if err != nil {
		return nil, nil, err
	}
	output, err := MarshalOpenAIResponseOutput(compaction.Output)
	if err != nil {
		return nil, compaction.Usage, err
	}
	if len(output) == 0 {
		return nil, compaction.Usage, errors.New("response compaction returned no output")
	}
	return output, compaction.Usage, nil
}

func MarshalOpenAIResponseOutput(output []any) ([]json.RawMessage, error) {
	if len(output) == 0 {
		return nil, nil
	}
	ret := make([]json.RawMessage, 0, len(output))
	for _, item := range output {
		data, err := json.Marshal(item)
		if err != nil {
			return nil, err
		}
		ret = append(ret, json.RawMessage(data))
	}
	return ret, nil
}

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Log compaction.Output before marshaling to see whether the provider returned anything at all
  2. Retry the compaction request — a transient empty generation often succeeds on retry
  3. Verify the response API version matches the struct field names (Output vs newer compaction fields)
  4. Handle the empty case upstream by skipping compaction for that turn instead of failing the conversation

Example fix

// before: assume compaction always yields output
output, usage, err := CompactOpenAIResponse(ctx, req)
// after: tolerate an empty compaction
output, usage, err := CompactOpenAIResponse(ctx, req)
if errors.Is(err, errEmptyCompactionOutput) { return fallbackToOriginalHistory(ctx, req) }
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check the compaction payload before calling
if len(compactionOutput) == 0 {
    return errors.New("provider returned an empty compaction output")
}

Try / catch

output, usage, err := CompactOpenAIResponse(ctx, req)
if err != nil && strings.Contains(err.Error(), "returned no output") {
    return fallbackToOriginalHistory(ctx, req), usage, nil // skip compaction this turn
}

Prevention

When it happens

Trigger: Calling createResponseCompaction/CompactOpenAIResponse when the provider's compaction response carries an empty (or nil) Output array despite returning success.

Common situations: Provider-side quirk where a compaction request returns an empty output list; a model that refused or produced nothing; API drift where output items moved to a different field (e.g. encrypted_content / compacted representation); filtering removed all output items before this check.

Understand the failure class

Background: "empty response", "returned no data", "empty embeddings": what HTTP 200-with-empty-body errors mean across libraries — this error's family across 36 libraries.

Related errors


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