{"record":{"id":"746cbf01220e198e","repo":"gofr-dev/gofr","slug":"w-w","errorCode":null,"errorMessage":"%w: %w","messagePattern":"%w: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/gofr/datasource/elasticsearch/elasticsearch.go","lineNumber":217,"sourceCode":"\treq := esapi.SearchRequest{\n\t\tIndex: indices,\n\t\tBody:  bytes.NewReader(body),\n\t}\n\n\tres, err := req.Do(tracedCtx, c.client)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"%w: executing search: %w\", errOperation, err)\n\t}\n\n\tdefer res.Body.Close()\n\n\tif res.IsError() {\n\t\treturn nil, fmt.Errorf(\"%w: %s\", errResponse, res.String())\n\t}\n\n\tvar result map[string]any\n\tif err := json.NewDecoder(res.Body).Decode(&result); err != nil {\n\t\treturn nil, fmt.Errorf(\"%w: %w\", errParsingResponse, err)\n\t}\n\n\tc.sendOperationStats(start, \"SEARCH\", indices, \"\", query, span)\n\n\treturn result, nil\n}\n\n// Bulk executes multiple indexing/updating/deleting operations in one request.\n// Each entry in `operations` should be a JSON‑serializable object\n// following the Elasticsearch bulk API format.\nfunc (c *Client) Bulk(ctx context.Context, operations []map[string]any) (map[string]any, error) {\n\tif len(operations) == 0 {\n\t\treturn nil, errEmptyOperations\n\t}\n\n\tstart := time.Now()\n\ttracedCtx, span := c.addTrace(ctx, \"bulk\", nil, \"\")\n","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/gofr-dev/gofr/blob/187eb24962502e91f1fee856230670958b66e89c/pkg/gofr/datasource/elasticsearch/elasticsearch.go#L199-L235","documentation":"Search() executes an Elasticsearch _search request and decodes the JSON response body into map[string]any. When json.Decoder.Decode fails — meaning the HTTP response body is not valid JSON or cannot unmarshal into the target — the call returns fmt.Errorf(\"%w: %w\", errParsingResponse, err), wrapping both the library sentinel errParsingResponse and the underlying decode error. This means the request itself succeeded (no transport error, non-error status) but the body could not be parsed.","triggerScenarios":"Calling Search() where the ES node returns a 200 response whose body is not valid JSON: truncated/garbled responses, a proxy or middleware rewriting the body, HTML error pages served with a 200 status by a load balancer, or a response body already consumed before decoding.","commonSituations":"Reverse proxies or service meshes intercepting traffic and returning HTML; ES nodes behind misconfigured gateways; custom ES plugins altering responses; testing against a fake/mock server that returns malformed JSON; TLS-terminating proxies injecting content.","solutions":["Inspect the wrapped error (errors.Unwrap / %v of the second error) to see the exact json syntax/unmarshal failure and the raw response via res.String() in logs.","Check what sits between the app and Elasticsearch (proxy, gateway, WAF) and verify it does not rewrite or replace response bodies.","Log response headers and status to confirm the reply is actually from an Elasticsearch node, not an intermediary returning HTML with status 200.","Ensure the Go Elasticsearch client version matches the server version; incompatible major versions can change response shapes.","Point the client directly at the ES node (bypass proxies) to isolate the cause."],"exampleFix":"// before\nresult, err := esClient.Search(ctx, indices, query)\n// after\nresult, err := esClient.Search(ctx, indices, query)\nif err != nil {\n    if strings.Contains(err.Error(), errParsingResponse.Error()) {\n        // response body was not valid JSON; log endpoint/proxy details\n        logger.Errorf(\"elasticsearch returned unparseable body: %v\", err)\n    }\n    return err\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"result, err := client.Search(ctx, indices, query)\nif err != nil {\n    if strings.Contains(err.Error(), \"parsing\") || strings.Contains(err.Error(), \"invalid character\") {\n        // body wasn't JSON: log endpoint, status, and any proxy details\n        return fmt.Errorf(\"elasticsearch search: non-JSON response: %w\", err)\n    }\n    return err\n}","preventionTips":["Monitor for intermediaries (proxies/WAFs) between app and ES and health-check that /_cluster/health returns JSON.","Assert response content-type is application/json in integration tests with the real cluster.","Keep ES Go client and server versions aligned."],"tags":["elasticsearch","json-parsing","response-decoding","golang"],"backgroundTag":"invalid-json-response","analyzedSha":"187eb24962502e91f1fee856230670958b66e89c","analyzedAt":"2026-09-01T20:34:54.554Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}