charmbracelet/crush · error

invalid response format: missing data field

Error message

invalid response format: missing data field

What it means

Raised by sourcegraphSearchResults when the parsed GraphQL response map lacks a "data" object (internal/agent/tools/sourcegraph.go:209-212). Sourcegraph returns {"data": {...}} on success; GraphQL-level failures arrive as a top-level "errors" array, which writeSourcegraphErrors handles first — so reaching this error means the 200 response was JSON but shaped unexpectedly (nil data, data as non-object, or an undocumented schema change).

Source

Thrown at internal/agent/tools/sourcegraph.go:211

	buffer.WriteString("## Sourcegraph API Error\n\n")
	for _, err := range errors {
		errMap, ok := err.(map[string]any)
		if !ok {
			continue
		}
		message, ok := errMap["message"].(string)
		if ok {
			fmt.Fprintf(buffer, "- %s\n", message)
		}
	}
	return true
}

func sourcegraphSearchResults(result map[string]any) (map[string]any, error) {
	data, ok := result["data"].(map[string]any)
	if !ok {
		return nil, fmt.Errorf("invalid response format: missing data field")
	}

	search, ok := data["search"].(map[string]any)
	if !ok {
		return nil, fmt.Errorf("invalid response format: missing search field")
	}

	searchResults, ok := search["results"].(map[string]any)
	if !ok {
		return nil, fmt.Errorf("invalid response format: missing results field")
	}
	return searchResults, nil
}

func writeSourcegraphHeader(buffer *strings.Builder, searchResults map[string]any) {
	matchCount, _ := searchResults["matchCount"].(float64)
	resultCount, _ := searchResults["resultCount"].(float64)
	limitHit, _ := searchResults["limitHit"].(bool)

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Log the full response body to see the actual top-level shape (errors array, null data, etc.).
  2. Check whether the response contained a GraphQL "errors" array whose entries were not {message:string} maps — extend writeSourcegraphErrors to surface raw entries.
  3. Verify sourcegraph.com's GraphQL schema is unchanged (introspect data.search) or pin/check a known-good Sourcegraph version for self-hosted endpoints.
  4. Treat this as the tool's 'Failed to format results' text error and retry with a simpler query to rule out query-induced null data.

Example fix

null
Defensive patterns

Strategy: type-guard

Validate before calling

if data, ok := result["data"].(map[string]any); !ok || data == nil {
    return fmt.Errorf("GraphQL response missing data: %v", result["errors"])
}

Type guard

func hasGraphQLData(result map[string]any) (map[string]any, bool) {
    data, ok := result["data"].(map[string]any)
    return data, ok && data != nil
}

Try / catch

formatted, err := formatSourcegraphResults(result, ctxWindow, count)
if err != nil {
    return fantasy.NewTextErrorResponse("Failed to format results: " + err.Error()), nil
}

Prevention

When it happens

Trigger: formatSourcegraphResults -> sourcegraphSearchResults sees result["data"] absent or not a map: GraphQL errors payload where only "errors" is present and writeSourcegraphErrors returned false (error entries not maps), a nil data field (Sourcegraph returns null data for some internal errors), or a Sourcegraph API schema/shape change.

Common situations: Sourcegraph returning {"data":null,"errors":[...]} with error entries the renderer skipped; partial (non-JSON-error) internal failures; using a modified/self-hosted endpoint with a different response shape; API version drift breaking the expected envelope.

Related errors


AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29). Data as JSON: /api/errors/c7a84eef71c2fccd. Report an issue: GitHub.