{"record":{"id":"cc7d04557b9a7bf5","repo":"siyuan-note/siyuan","slug":"compaction-summary-stream-failed-w","errorCode":null,"errorMessage":"compaction summary stream failed: %w","messagePattern":"compaction summary stream failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/agent/compaction.go","lineNumber":228,"sourceCode":"\tdefer stream.Close()\n\tdefer cancel()\n\n\tvar summaryBuilder strings.Builder\n\tfirstResponsePending := true\n\tfor {\n\t\tresponse := firstResponse\n\t\tvar receiveErr error\n\t\tif firstResponsePending {\n\t\t\tfirstResponsePending = false\n\t\t} else {\n\t\t\tresponse, receiveErr = recvStreamWithIdleTimeout(stream, streamIdleTimeout, cancel)\n\t\t}\n\t\tif receiveErr != nil {\n\t\t\tif errors.Is(receiveErr, io.EOF) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\treturn \"\", promptTokens, completionTokens,\n\t\t\t\tfmt.Errorf(\"compaction summary stream failed: %w\", receiveErr)\n\t\t}\n\t\tfor _, choice := range response.Choices {\n\t\t\tsummaryBuilder.WriteString(choice.Delta.Content)\n\t\t}\n\t\tif response.Usage != nil {\n\t\t\tpromptTokens = response.Usage.PromptTokens\n\t\t\tcompletionTokens = response.Usage.CompletionTokens\n\t\t}\n\t}\n\tsummary = strings.TrimSpace(summaryBuilder.String())\n\tif summary == \"\" {\n\t\treturn \"\", promptTokens, completionTokens, errCompactionSummaryEmpty\n\t}\n\treturn summary, promptTokens, completionTokens, nil\n}\n\nfunc createResponseCompaction(ctx context.Context, client *openai.Client, request openai.ChatCompletionRequest,\n\tresponseInput []any, maxRetries int, requestTimeout time.Duration,","sourceCodeStart":210,"sourceCodeEnd":246,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/agent/compaction.go#L210-L246","documentation":"Wraps a mid-stream failure of the compaction summary request. The request started successfully, but receiving a stream chunk returned a non-EOF error (network drop, provider stream error event, idle-timeout on the stream), so partial token counts and the incomplete summary are discarded and the error is wrapped for reporting.","triggerScenarios":"During createProtocolCompactionSummary's receive loop: stream receive returns an error other than io.EOF — connection reset, stream idle timeout exceeded, provider sending an error event mid-stream, or the stream being closed unexpectedly.","commonSituations":"Long summary generations interrupted by unstable networks (mobile, VPN, proxies); providers closing idle streams; server-side overload dropping the SSE connection; streamIdleTimeout too aggressive for a slow model.","solutions":["Retry the compaction; the wrapper's cause tells whether it was a timeout, reset, or API error","Increase streamIdleTimeout if the model pauses between chunks","Check network stability (VPN/proxy) or switch to a more reliable provider endpoint","Reduce summary size (lower compactionSummaryMaxTokens) so the stream finishes faster"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err != nil { if ne, ok := err.(net.Error); ok && ne.Timeout() { /* increase streamIdleTimeout and retry */ }; return fmt.Errorf(\"compaction aborted: %w\", err) }","preventionTips":["Use stable networks (avoid flaky VPN/proxy) for long streaming requests","Tune streamIdleTimeout to accommodate slow models","Prefer providers with reliable SSE implementations","Persist partial progress or resumable state where possible"],"tags":["agent","compaction","streaming","network","llm"],"backgroundTag":"broken-pipe","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}