{"record":{"id":"d702fd912e2b39c6","repo":"Tencent/WeKnora","slug":"summary-generation-exhausted-retries-w","errorCode":null,"errorMessage":"summary generation exhausted retries: %w","messagePattern":"summary generation exhausted retries: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/application/service/knowledge_process.go","lineNumber":1215,"sourceCode":"\t\tif stale {\n\t\t\tlogger.Infof(ctx, \"Discarding stale summary fallback for knowledge %s\", payload.KnowledgeID)\n\t\t\tsummaryOut[\"skipped\"] = \"content_revision_changed\"\n\t\t\treturn nil\n\t\t}\n\n\t\tfallback := applyRetryableSummaryFailureState(knowledge, textChunks, false)\n\t\tif updateErr := s.repo.UpdateKnowledge(ctx, knowledge); updateErr != nil {\n\t\t\tlogger.Errorf(ctx, \"Failed to save terminal summary fallback: %v\", updateErr)\n\t\t\tsummaryErr = updateErr\n\t\t\treturn fmt.Errorf(\"save terminal summary fallback: %w\", updateErr)\n\t\t}\n\t\tif fallback == \"\" {\n\t\t\tsummaryOut[\"fallback\"] = \"empty\"\n\t\t} else {\n\t\t\tsummaryOut[\"fallback\"] = \"first_chunk\"\n\t\t}\n\t\tsummaryOut[\"fallback_chars\"] = len([]rune(fallback))\n\t\treturn fmt.Errorf(\"summary generation exhausted retries: %w\", generationErr)\n\t}\n\n\t// Initialize chat model for summary. Model resolution failures use the same\n\t// retry budget and terminal first-chunk fallback as LLM request failures.\n\tchatModel, err := s.modelService.GetChatModel(ctx, kb.SummaryModelID)\n\tif err != nil {\n\t\tlogger.Errorf(ctx, \"Failed to get chat model: %v\", err)\n\t\treturn handleRetryableSummaryFailure(fmt.Errorf(\"get chat model: %w\", err))\n\t}\n\n\t// Generate summary\n\tsummary, err := s.getSummary(ctx, chatModel, knowledge, textChunks)\n\tif err != nil {\n\t\tlogger.Errorf(ctx, \"Failed to generate summary for knowledge %s: %v\", payload.KnowledgeID, err)\n\t\t// Surface the underlying LLM/IO error on the span so the trace UI\n\t\t// can explain \"why did this stage take 60s and then fall back?\"\n\t\t// without forcing the operator to grep worker logs. We also capture\n\t\t// the error type to disambiguate timeouts from upstream HTTP errors","sourceCodeStart":1197,"sourceCodeEnd":1233,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/service/knowledge_process.go#L1197-L1233","documentation":"Terminal error returned after summary generation exhausted its retry budget. By the time it is returned, a degraded fallback (first chunk or empty summary) has already been persisted to the knowledge record, so this error signals stage outcome, not data loss.","triggerScenarios":"Thrown at internal/application/service/knowledge_process.go:1215 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Inspect summaryOut['error']/['error_type'] on the span to identify the LLM/IO root cause (timeout, upstream 5xx, quota)","Fix the underlying model/config issue, then re-trigger summary regeneration","The knowledge remains searchable via chunks with the fallback summary until then"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}