{"record":{"id":"cdd0fc975adaaaa5","repo":"vxcontrol/pentagi","slug":"internal-engine-summarization-failed-w","errorCode":null,"errorMessage":"internal engine: summarization failed: %w","messagePattern":"internal engine: summarization failed: %w","errorType":"exception","errorClass":"RetryableError","httpStatus":null,"severity":"error","filePath":"backend/pkg/tools/searchers/internal.go","lineNumber":178,"sourceCode":"\t\t// [Source N]; usedURLs tracks the matching URL so it can be listed at the end.\n\t\tblocks = append(blocks, fmt.Sprintf(\"<source id=\\\"%d\\\" url=\\\"%s\\\">\\n%s\\n</source>\", fetched+1, u, md))\n\t\tusedURLs = append(usedURLs, u)\n\t\tfetched++\n\t}\n\n\tif fetched == 0 {\n\t\t// Nothing could be read. If the pages errored (vs. returned empty), surface a\n\t\t// retryable error so the orchestrator can fall back to another engine.\n\t\tif lastFetch != nil {\n\t\t\treturn \"\", Retryable(fmt.Errorf(\"internal engine: all pages failed to fetch: %w\", lastFetch), 0)\n\t\t}\n\t\treturn \"\", Fatal(fmt.Errorf(\"internal engine: no readable content found\"))\n\t}\n\n\tprompt := e.buildPrompt(req.Query, blocks)\n\tanswer, serr := e.summarizer(ctx, prompt)\n\tif serr != nil {\n\t\treturn \"\", Retryable(fmt.Errorf(\"internal engine: summarization failed: %w\", serr), 0)\n\t}\n\n\treturn appendSources(answer, usedURLs), nil\n}\n\n// appendSources appends the list of source URLs the answer was synthesized from, so the\n// [Source N] citations in the summary can be traced back to the page they came from. The\n// numbering matches the source ids fed to the summarizer (1-based, in fetch order).\nfunc appendSources(answer string, urls []string) string {\n\tif len(urls) == 0 {\n\t\treturn answer\n\t}\n\tvar sb strings.Builder\n\tsb.WriteString(strings.TrimRight(answer, \"\\n\"))\n\tsb.WriteString(\"\\n\\n### Sources\\n\\n\")\n\tfor i, u := range urls {\n\t\tparsedURL, err := url.Parse(u)\n\t\tif err != nil {","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/tools/searchers/internal.go#L160-L196","documentation":"After pages are fetched, the internal engine builds a prompt (`buildPrompt`) and calls `e.summarizer(ctx, prompt)` — an LLM call that synthesizes the answer. If the summarizer returns an error, it is wrapped as Retryable with this message (backend/pkg/tools/searchers/internal.go:178), since an LLM outage is usually transient and the orchestrator can retry or fall back.","triggerScenarios":"The LLM backing the internal engine's summarizer fails: provider API key invalid/quota exhausted, model unavailable, request context deadline exceeded, rate limit (429), or the provider returns 5xx.","commonSituations":"No LLM provider key configured (or only optional ones set); provider quota/billing exhausted mid-run; LLM provider outage; context window exceeded because the fetched pages were large (WebSearchInternalMaxSiteBytes set too high).","solutions":["Check the wrapped cause in the error message — it carries the provider's own error (401/429/5xx/timeout) and fix that specifically","Verify at least one valid LLM provider key is configured in .env / Settings UI","Retry — the error is typed Retryable, so transient provider failures are recoverable","Lower WebSearchInternalMaxSiteBytes (or WebSearchInternalMaxSites) to shrink the prompt if it is exceeding the model's context window"],"exampleFix":"// before: prompt too large for the model\nWEB_SEARCH_INTERNAL_MAX_SITE_BYTES=1000000\n// after\nWEB_SEARCH_INTERNAL_MAX_SITE_BYTES=100000","handlingStrategy":"retry","validationCode":"// ensure a summarizer-capable provider is configured before invoking\nif cfg.PrimaryProviderAPIKey == \"\" {\n    return errors.New(\"no LLM provider configured for internal search summarizer\")\n}","typeGuard":null,"tryCatchPattern":"_, err := engine.Handle(ctx, req)\nif err != nil {\n    if searchers.IsRetryable(err) {\n        // backoff and retry; check wrapped provider error for 401/429/5xx\n    }\n}","preventionTips":["Configure and validate at least one LLM provider key at startup","Watch provider quota/billing; 429s surface as this error","Cap WebSearchInternalMaxSites/MaxSiteBytes so prompts stay within the model context window","Add provider health checks in observability dashboards"],"tags":["llm","summarization","network"],"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"}