googleapis/mcp-toolbox · error

failed to decode response body: %w

Error message

failed to decode response body: %w

What it means

Thrown in RunSQL when the ES|QL query succeeds (no HTTP error) but the response body cannot be decoded into the EsqlResult struct {columns, values}. Note FilterPath restricts the response to columns/values, so the wrapper means the JSON shape differed from expectations or was corrupt.

Source

Thrown at internal/sources/elasticsearch/elasticsearch.go:207

	if err != nil {
		return nil, err
	}
	defer res.Body.Close()

	if res.IsError() {
		// Try to extract error message from response
		var esErr json.RawMessage
		err = util.DecodeJSON(res.Body, &esErr)
		if err != nil {
			return nil, fmt.Errorf("elasticsearch error: status %s", res.Status())
		}
		return esErr, nil
	}

	var result EsqlResult
	err = util.DecodeJSON(res.Body, &result)
	if err != nil {
		return nil, fmt.Errorf("failed to decode response body: %w", err)
	}

	output := EsqlToMap(result)

	return output, nil
}

// EsqlToMap converts the esqlResult to a slice of maps.
func EsqlToMap(result EsqlResult) []map[string]any {
	output := make([]map[string]any, 0, len(result.Values))
	for _, value := range result.Values {
		row := make(map[string]any)
		if value == nil {
			output = append(output, row)
			continue
		}
		for i, col := range result.Columns {
			if i < len(value) {

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Ensure `format` is empty or "json" so the response body is JSON
  2. Check Elasticsearch version supports ES|QL (8.11+ or serverless)
  3. Inspect the raw response with curl (`POST /_query?format=json`) to see the actual body
  4. Remove any proxy that alters response bodies

Example fix

// before (tools.yaml tool parameter)
format: "csv"
// after
format: "json"
Defensive patterns

Strategy: validation

Validate before calling

// only JSON output can be decoded by the toolbox
if format != "" && format != "json" {
    return fmt.Errorf("format %q not supported; use empty or \"json\"", format)
}

Try / catch

// Go
out, err := src.RunSQL(ctx, format, query, params)
if err != nil && strings.Contains(err.Error(), "failed to decode response body") {
    // check format param and ES version; retry with format="json"
}

Prevention

When it happens

Trigger: The `format` parameter requests a non-JSON format (e.g. csv, tsv) so the body is not JSON at all; a proxy rewrites the body; an intermediate error page appears with a 200; or ES returns a JSON shape missing `columns`/`values`.

Common situations: Users setting format to csv/text in the tool config expecting delimited output — the client still tries to JSON-decode it; LLM passing format values unsupported for JSON decoding; old Elasticsearch versions (<8.11) lacking the _query endpoint and returning something unexpected.

Understand the failure class

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/5facd111072b5a48. Report an issue: GitHub.