{"record":{"id":"efac70e49b965bd9","repo":"vxcontrol/pentagi","slug":"summarization-failed-w","errorCode":null,"errorMessage":"summarization failed: %w","messagePattern":"summarization failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/csum/chain_summary.go","lineNumber":802,"sourceCode":"\thandler tools.SummarizeHandler,\n\thumanMessages []llms.MessageContent,\n\taiMessages []llms.MessageContent,\n) (string, error) {\n\tif handler == nil {\n\t\treturn \"\", fmt.Errorf(\"summarizer handler cannot be nil\")\n\t}\n\n\tif len(humanMessages) == 0 && len(aiMessages) == 0 {\n\t\treturn \"\", fmt.Errorf(\"cannot summarize empty message list\")\n\t}\n\n\t// Convert messages to text format optimized for summarization\n\ttext := messagesToPrompt(humanMessages, aiMessages)\n\n\t// Generate the summary using provided summarizer handler\n\tsummary, err := handler(ctx, text)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"summarization failed: %w\", err)\n\t}\n\n\treturn summary, nil\n}\n\n// messagesToPrompt converts a slice of messages to a text representation\nfunc messagesToPrompt(humanMessages []llms.MessageContent, aiMessages []llms.MessageContent) string {\n\tvar buffer strings.Builder\n\n\thumanMessagesText := humanMessagesToText(humanMessages)\n\taiMessagesText := aiMessagesToText(aiMessages)\n\n\t// case 0: no messages\n\tif len(humanMessages) == 0 && len(aiMessages) == 0 {\n\t\treturn \"nothing to summarize\"\n\t}\n\n\t// case 1: use human messages as a context for ai messages","sourceCodeStart":784,"sourceCodeEnd":820,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/csum/chain_summary.go#L784-L820","documentation":"GenerateSummary builds a text prompt from human/AI messages and delegates the actual summarization to a caller-supplied handler (typically an LLM call). If that handler returns an error it is wrapped as \"summarization failed: %w\". The error means the summarization backend (LLM provider) failed — rate limit, timeout, auth, or context-too-long — not that the chain-summary logic itself is wrong.","triggerScenarios":"The injected summarizer handler (LLM invocation) fails during getTaskPrimaryAgentChainSummary, summarizeLastSection, or summarizeQAPairs: provider API returns 401/429/5xx, the request exceeds the model's context window, network timeout, or ctx cancellation.","commonSituations":"Expired or missing LLM API key; provider rate limits during long-running flows with big message chains; model context window too small for the accumulated messages; transient network failures to the provider endpoint.","solutions":["Unwrap the error and check the provider failure: fix API keys/quota if 401/429.","Retry with backoff for transient (429/5xx/network) failures — the handler is usually retryable.","Reduce input size: chunk messages into smaller sections or use a larger-context model for summarization.","Verify the provider configuration (base URL, model name) in settings/env.","Check ctx deadlines; increase timeout if large summaries are being truncated."],"exampleFix":"// before\nsummary, err := handler(ctx, text)\nif err != nil { return \"\", err }\n// after\nsummary, err := handler(ctx, text)\nif err != nil {\n    if errors.Is(err, context.DeadlineExceeded) {\n        tctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)\n        defer cancel()\n        return handler(tctx, truncateText(text, maxChunk))\n    }\n    return \"\", fmt.Errorf(\"summarization failed: %w\", err)\n}","handlingStrategy":"retry","validationCode":"if handler == nil {\n    return \"\", fmt.Errorf(\"no summarizer configured\")\n}\nif err := ctx.Err(); err != nil {\n    return \"\", err\n}\nif len(text) > maxSummarizationChars {\n    text = truncateText(text, maxSummarizationChars) // avoid context-window overflow\n}","typeGuard":"func isRetryableSummaryError(err error) bool {\n    var apiErr *openai.Error // or provider-specific error type\n    if errors.As(err, &apiErr) {\n        return apiErr.HTTPStatusCode == 429 || apiErr.HTTPStatusCode >= 500\n    }\n    return errors.Is(err, context.DeadlineExceeded) || errors.Is(err, io.ErrUnexpectedEOF)\n}","tryCatchPattern":"summary, err := GenerateSummary(ctx, humanMsgs, aiMsgs, handler)\nif err != nil {\n    if isRetryableSummaryError(err) {\n        summary, err = retryWithBackoff(3, func() (string, error) {\n            return GenerateSummary(ctx, humanMsgs, aiMsgs, handler)\n        })\n    }\n    if err != nil {\n        return fallbackSummary(text) // extractive stub instead of failing the chain\n    }\n}","preventionTips":["Keep LLM provider keys and quotas healthy; alert on 401/429 rates.","Cap message-chain text size before calling the summarizer.","Set generous timeouts for summarization calls on long flows.","Cache chain summaries to avoid repeated expensive LLM calls.","Provide a non-LLM fallback summary path."],"tags":["go","llm","summarization","provider-failure"],"backgroundTag":"llm-provider-request-failed","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}