{"record":{"id":"9fb9d99af0565903","repo":"gofr-dev/gofr","slug":"invalid-elasticsearch-response","errorCode":null,"errorMessage":"invalid elasticsearch response","messagePattern":"invalid elasticsearch response","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/gofr/datasource/elasticsearch/elasticsearch.go","lineNumber":33,"sourceCode":"\t\"go.opentelemetry.io/otel/trace\"\n)\n\nconst (\n\tstatusDown     = \"DOWN\"\n\tstatusUp       = \"UP\"\n\tdefaultTimeout = 5 * time.Second\n)\n\nvar (\n\terrEmptyIndex        = errors.New(\"index name cannot be empty\")\n\terrEmptyDocumentID   = errors.New(\"document ID cannot be empty\")\n\terrEmptyQuery        = errors.New(\"query cannot be empty\")\n\terrEmptyOperations   = errors.New(\"operations cannot be empty\")\n\terrHealthCheckFailed = errors.New(\"elasticsearch health check failed\")\n\terrOperation         = errors.New(\"elasticsearch operation error\")\n\terrMarshaling        = errors.New(\"error marshaling data\")\n\terrParsingResponse   = errors.New(\"error parsing response\")\n\terrResponse          = errors.New(\"invalid elasticsearch response\")\n\terrEncodingOperation = errors.New(\"error encoding operation\")\n)\n\n// Config holds the configuration for connecting to Elasticsearch.\ntype Config struct {\n\tAddresses []string\n\tUsername  string\n\tPassword  string\n}\n\n// Client represents the Elasticsearch client.\ntype Client struct {\n\tconfig  Config\n\tclient  *es.Client\n\tlogger  Logger\n\tmetrics Metrics\n\ttracer  trace.Tracer\n}","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/gofr-dev/gofr/blob/187eb24962502e91f1fee856230670958b66e89c/pkg/gofr/datasource/elasticsearch/elasticsearch.go#L15-L51","documentation":"errResponse (\"invalid elasticsearch response\") is the sentinel error wrapped when the Elasticsearch HTTP response itself indicates an error. The client sends the request successfully, the server answers, but res.IsError() reports a 4xx/5xx status. The full raw ES response (status line and error body) is embedded via res.String(), so the underlying cause (bad query DSL, missing index, auth failure, mapping conflict) is visible in the wrapped message.","triggerScenarios":"Any call to IndexDocument, GetDocument, UpdateDocument, DeleteDocument, CreateIndex, or DeleteIndex where the ES cluster returns an HTTP error status: e.g. CreateIndex on an index that already exists (resource_already_exists_exception), Search/GetDocument on a nonexistent index (index_not_found_exception), UpdateDocument/DeleteDocument on a missing document, invalid query DSL (parsing_exception), or 401/403 from bad credentials.","commonSituations":"Developers hit this when an index was never created (or a migration didn't run), when the query body has invalid Elasticsearch DSL for the cluster's version (e.g. newer DSL on an older cluster), when credentials lack write permissions, or when the document ID typed in code doesn't exist.","solutions":["Read the res.String() payload in the wrapped error to get the exact ES error type and reason (e.g. index_not_found_exception vs parsing_exception).","If index_not_found_exception, create the index first (call CreateIndex) or verify the index name spelling/environment.","If parsing_exception or a DSL version issue, validate the query/settings JSON against the ES version's documentation.","If 401/403, fix Config.Username/Password or the user's index-level permissions.","If resource_already_exists_exception on CreateIndex, treat as idempotent: check index existence before creating."],"exampleFix":"// before\nif err := client.CreateIndex(ctx, \"orders\", settings); err != nil {\n    return err // invalid elasticsearch response: [ES response with resource_already_exists_exception]\n}\n// after\nif err := client.CreateIndex(ctx, \"orders\", settings); err != nil {\n    if strings.Contains(err.Error(), \"resource_already_exists_exception\") {\n        return nil // index already exists - safe to proceed\n    }\n    return err\n}","handlingStrategy":"type-guard","validationCode":"// before calling the API, validate arguments the cluster would reject\nif strings.TrimSpace(index) == \"\" { return errors.New(\"index required\") }\n// confirm the index exists to avoid index_not_found:\n// GET /_cat/indices/<index> via HealthCheck or a HEAD request","typeGuard":"func IsESResponseError(err error) bool {\n    return errors.Is(err, errResponseSentinel) || strings.Contains(err.Error(), \"invalid elasticsearch response\")\n}\n\nfunc ESExceptionIs(err error, exception string) bool {\n    return IsESResponseError(err) && strings.Contains(err.Error(), exception)\n}","tryCatchPattern":"if err := client.GetDocument(ctx, index, id); err != nil {\n    switch {\n    case strings.Contains(err.Error(), \"index_not_found_exception\"):\n        // create index or fix name\n    case strings.Contains(err.Error(), \"401\") || strings.Contains(err.Error(), \"403\"):\n        // fix credentials/permissions\n    default:\n        return fmt.Errorf(\"elasticsearch get failed: %w\", err)\n    }\n}","preventionTips":["Always log the full wrapped error; res.String() contains the exact ES exception type.","Run index-creation migrations idempotently before document operations.","Use per-environment index-name constants instead of inline strings.","Check HealthCheck at startup so auth/connectivity issues surface early."],"tags":["elasticsearch","http-response","server-error"],"backgroundTag":"elasticsearch-error-response","analyzedSha":"187eb24962502e91f1fee856230670958b66e89c","analyzedAt":"2026-09-01T20:34:54.554Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}