{"record":{"id":"9fd493683edbdb9e","repo":"googleapis/mcp-toolbox","slug":"elasticsearch-error-status-s","errorCode":null,"errorMessage":"elasticsearch error: status %s","messagePattern":"elasticsearch error: status (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/sources/elasticsearch/elasticsearch.go","lineNumber":199,"sourceCode":"\n\tres, err := esapi.EsqlQueryRequest{\n\t\tBody:       bytes.NewReader(body),\n\t\tFormat:     format,\n\t\tFilterPath: []string{\"columns\", \"values\"},\n\t\tInstrument: s.ElasticsearchClient().InstrumentationEnabled(),\n\t}.Do(ctx, s.ElasticsearchClient())\n\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer res.Body.Close()\n\n\tif res.IsError() {\n\t\t// Try to extract error message from response\n\t\tvar esErr json.RawMessage\n\t\terr = util.DecodeJSON(res.Body, &esErr)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"elasticsearch error: status %s\", res.Status())\n\t\t}\n\t\treturn esErr, nil\n\t}\n\n\tvar result EsqlResult\n\terr = util.DecodeJSON(res.Body, &result)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to decode response body: %w\", err)\n\t}\n\n\toutput := EsqlToMap(result)\n\n\treturn output, nil\n}\n\n// EsqlToMap converts the esqlResult to a slice of maps.\nfunc EsqlToMap(result EsqlResult) []map[string]any {\n\toutput := make([]map[string]any, 0, len(result.Values))","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/sources/elasticsearch/elasticsearch.go#L181-L217","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// test the ES|QL query directly to get a real JSON error body\ncurl -u \"$ES_USER:$ES_PASS\" -H 'Content-Type: application/json' \\\n  'http://localhost:9200/_query?format=json' -d '{\"query\":\"FROM index | LIMIT 10\"}'","typeGuard":null,"tryCatchPattern":"// Go: the returned error carries only the status; log it and retry or inspect server-side\nout, err := src.RunSQL(ctx, format, query, params)\nif err != nil && strings.Contains(err.Error(), \"elasticsearch error: status\") {\n    slog.WarnContext(ctx, \"ES error with unreadable body\", \"status\", err)\n    // fall back to direct cluster query for the detailed reason\n}","preventionTips":["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"],"tags":["elasticsearch","http-status","response-parsing","esql"],"backgroundTag":"http-error-response","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}