alibaba/open-code-review · error

grouping response parse failed: %w

Error message

grouping response parse failed: %w

What it means

This error is recorded on the session recorder (not returned to the caller) when the grouping LLM produced non-empty content, but parseGroupingResponse failed to turn that content into valid grouping JSON. The underlying parse error (unknown JSON syntax, wrong shape) is wrapped with %w, so the real cause is chained. The call still returns the raw parse error to the caller; this message is the recorded audit-trail entry.

Source

Thrown at internal/agent/grouping.go:236

			rec.SetError(err, duration)
		}
		return nil, nil, fmt.Errorf("grouping LLM call: %w", err)
	}

	usage = resp.Usage

	content := resp.Content()
	if content == "" {
		if rec != nil {
			rec.SetError(fmt.Errorf("grouping LLM returned empty response"), duration)
		}
		return nil, usage, fmt.Errorf("grouping LLM returned empty response")
	}

	groups, err = parseGroupingResponse(content, diffs)
	if rec != nil {
		if err != nil {
			rec.SetError(fmt.Errorf("grouping response parse failed: %w", err), duration)
		} else {
			rec.SetResponse(resp, duration)
		}
	}
	return groups, usage, err
}

func buildFileList(diffs []model.Diff) string {
	var sb strings.Builder
	for _, d := range diffs {
		sb.WriteString(formatDiffEntry(d))
		sb.WriteString("\n")
	}
	return sb.String()
}

func parseGroupingResponse(content string, diffs []model.Diff) ([]FileGroup, error) {
	content = strings.TrimSpace(content)

View on GitHub (pinned to 5cf97d0d15)

Solutions

  1. Check the recorded session error for the wrapped underlying parse error to see exactly what json.Unmarshal rejected
  2. Increase maxTokens so the grouping JSON is not truncated
  3. Strengthen the grouping prompt to demand only a bare JSON array, or retry the LLM call
  4. Validate the response shape in parseGroupingResponse and surface the offending content snippet in logs

Example fix

// before (model returned prose + JSON)
groups, err = parseGroupingResponse(content, diffs)
// after (extract first [...] block before parsing)
content = extractJSON(content)
groups, err = parseGroupingResponse(content, diffs)
Defensive patterns

Strategy: validation

Validate before calling

func validGrouping(content string) bool {
    c := strings.TrimSpace(content)
    if strings.HasPrefix(c, "```") { c = stripFences(c) }
    var probe []map[string]any
    return json.Unmarshal([]byte(c), &probe) == nil && len(probe) > 0
}

Type guard

func isJSONArray(raw string) bool {
    var v []any
    return json.Unmarshal([]byte(raw), &v) == nil
}

Try / catch

groups, _, err := callGroupingLLM(ctx, client, ...)
if err != nil {
    log.Warnf("grouping parse failed, falling back to single group: %v", err)
    groups = fallbackSingleGroup(diffs)
}

Prevention

When it happens

Trigger: callGroupingLLM receives a non-empty LLM response whose content, after markdown fence stripping, is not a JSON array of {label, files} objects — e.g. the model answered in prose, returned truncated JSON (max_tokens cut mid-array), or wrapped the JSON in explanatory text beyond the leading/trailing fence.

Common situations: Small max_tokens budgets truncating long file lists; weaker models that ignore the 'respond only with JSON' instruction; providers that emit reasoning text before the JSON; responses with trailing commas or comments.

Related errors


AI-assisted analysis of alibaba/open-code-review@5cf97d0d15 (2026-09-02). Data as JSON: /api/errors/063696dea30c0267. Report an issue: GitHub.