googleapis/mcp-toolbox · error
elasticsearch error: status %s
Error message
elasticsearch error: status %s
What it means
Thrown in RunSQL when Elasticsearch returns an error response but its body cannot be parsed as JSON (DecodeJSON fails). The code falls back to reporting the HTTP status string (e.g. '400 Bad Request') since the detailed error reason was unreadable.
Source
Thrown at internal/sources/elasticsearch/elasticsearch.go:199
res, err := esapi.EsqlQueryRequest{
Body: bytes.NewReader(body),
Format: format,
FilterPath: []string{"columns", "values"},
Instrument: s.ElasticsearchClient().InstrumentationEnabled(),
}.Do(ctx, s.ElasticsearchClient())
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))View on GitHub (pinned to 8cc6e09de2)
Solutions
- Check the status string in the message and fix the underlying HTTP issue (e.g. 502/504 → check proxy; 400 → fix query)
- Bypass any proxy/load balancer and query Elasticsearch directly to get a real JSON error body
- Validate the ES|QL query syntax against the cluster (`POST /_query` with curl)
- Retry the query; transient gateway errors often return non-JSON bodies
Defensive patterns
Strategy: fallback
Validate before calling
// test the ES|QL query directly to get a real JSON error body
curl -u "$ES_USER:$ES_PASS" -H 'Content-Type: application/json' \
'http://localhost:9200/_query?format=json' -d '{"query":"FROM index | LIMIT 10"}' Try / catch
// Go: the returned error carries only the status; log it and retry or inspect server-side
out, err := src.RunSQL(ctx, format, query, params)
if err != nil && strings.Contains(err.Error(), "elasticsearch error: status") {
slog.WarnContext(ctx, "ES error with unreadable body", "status", err)
// fall back to direct cluster query for the detailed reason
} Prevention
- Avoid proxies that rewrite error bodies between toolbox and Elasticsearch
- Validate ES|QL syntax before deploying the tool config
- Watch for HTML error pages (502/504) from gateways — they trigger this fallback
When it happens
Trigger: The ES|QL query endpoint returns an error (res.IsError()) whose body is empty, truncated, HTML (from a proxy/load balancer), or gzip/charset content the decoder cannot read — then the raw status is surfaced instead.
Common situations: Malformed ES|QL syntax triggering an error response behind a proxy that rewrites the body; intermediate gateways returning HTML 502/504 pages; response body already consumed or streaming interrupted.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- failed to decode response body: %w
- elasticsearch connection failed: status %d
- failed to decode response: %w
- error getting user agent from context: %w
- elasticsearch source %q requires either username/password or
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/9fd493683edbdb9e.
Report an issue: GitHub.