{"record":{"id":"1ab02172a3fac107","repo":"alibaba/open-code-review","slug":"grouping-llm-panicked-v","errorCode":null,"errorMessage":"grouping LLM panicked: %v","messagePattern":"grouping LLM panicked: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/agent/grouping.go","lineNumber":173,"sourceCode":"// FileGroup exists, so it describes the change set the way review.started does,\n// rather than the group-scoped spans that pair group.file_count with a\n// group.label there is none of here.\nfunc emitGroupingSkipped(ctx context.Context, strategy template.GroupingStrategy, fileCount int, totalChanged int64, tpl template.Template) {\n\ttelemetry.Event(ctx, \"grouping.skipped\",\n\t\ttelemetry.AnyToAttr(\"strategy\", strategy.String()),\n\t\ttelemetry.AnyToAttr(\"file.count\", fileCount),\n\t\ttelemetry.AnyToAttr(\"lines.changed\", totalChanged),\n\t\ttelemetry.AnyToAttr(\"threshold.files\", tpl.GroupingMinFiles),\n\t\ttelemetry.AnyToAttr(\"threshold.lines\", tpl.GroupingBundleLineThreshold))\n}\n\nfunc callGroupingLLM(ctx context.Context, diffs []model.Diff, client llm.LLMClient, modelName string, task *template.LlmConversation, maxTokens int, sessOpts *groupingSessionOpts) (groups []FileGroup, usage *llm.UsageInfo, err error) {\n\tvar rec *session.TaskRecord\n\tstartTime := time.Now()\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tgroups = nil\n\t\t\terr = fmt.Errorf(\"grouping LLM panicked: %v\", r)\n\t\t\tif rec != nil {\n\t\t\t\trec.Response = nil\n\t\t\t\trec.SetError(err, time.Since(startTime))\n\t\t\t}\n\t\t}\n\t}()\n\n\tfileList := buildFileList(diffs)\n\n\tmessages := make([]llm.Message, 0, len(task.Messages))\n\tfor _, m := range task.Messages {\n\t\tcontent := strings.ReplaceAll(m.Content, \"{{file_list}}\", fileList)\n\t\tmessages = append(messages, llm.NewTextMessage(m.Role, content))\n\t}\n\n\tconst groupingFileKey = \"__grouping__\"\n\n\tif sessOpts != nil && sessOpts.session != nil {","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/internal/agent/grouping.go#L155-L191","documentation":"callGroupingLLM installs a deferred recover() and, if the grouping LLM call path panics (nil pointer, index out of range, nil map write in response handling, etc.), converts the panic into this error and clears the task record response. This prevents a panic in LLM response processing from crashing the whole review process.","triggerScenarios":"A panic anywhere between callGroupingLLM entry and return — typically while handling a malformed/nil LLM response or usage object inside the grouping call path.","commonSituations":"Provider SDK returning an unexpected response shape (nil resp dereferenced), template misconfiguration causing nil message slices, or a bug triggered by an unusual API response (e.g. resp with nil Usage accessed by recoverable code).","solutions":["Look at the %v value in the message — it names the panic (e.g. 'runtime error: invalid memory address').","Check the session task record; rec.Response is cleared, so rely on the error string and logs.","Re-run; if reproducible, inspect the LLM response that triggered it (enable debug logging) and the template configuration.","Report as a bug with the panic text and model/provider if input is well-formed — the recover is a safety net, not an expected path."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// the library already recovers; callers should treat the returned error as fatal-but-safe\nif groups, _, err := callGroupingLLM(ctx, diffs, client, model, task, maxTokens, opts); err != nil {\n    log.Printf(\"grouping failed: %v\", err) // includes panic text after 'grouping LLM panicked:'\n    return fallbackGrouping(diffs)\n}","preventionTips":["Keep the LLM client/provider SDK versions in sync with this library to avoid unexpected response shapes.","Enable debug logging of raw responses when investigating reproducible panics.","Do not pass nil template/session options into the pipeline.","Report panics with the exact %v text — recovery masks the stack trace, so logs matter."],"tags":["panic","llm","grouping","recovery"],"backgroundTag":"panic-converted-to-error","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}