{"record":{"id":"d5892eee0107f2a0","repo":"gofr-dev/gofr","slug":"error-parsing-response","errorCode":null,"errorMessage":"error parsing response","messagePattern":"error parsing response","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/gofr/datasource/elasticsearch/elasticsearch.go","lineNumber":32,"sourceCode":"\t\"go.opentelemetry.io/otel/attribute\"\n\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","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/gofr-dev/gofr/blob/187eb24962502e91f1fee856230670958b66e89c/pkg/gofr/datasource/elasticsearch/elasticsearch.go#L14-L50","documentation":"Same errClaimPathNotFound family as the mid-path case: during nested traversal the next key does not exist in the current map (next == false after map lookup), so the library returns the error with the fully traversed prefix. Reached whenever a map exists at the current level but lacks the requested segment.","triggerScenarios":"Path \"permissions.role\" where claims[\"permissions\"] is a map but has no \"role\" key; missing deeper keys like \"realm_access.roles\" when realm_access exists but roles was dropped.","commonSituations":"User tokens without the specific role entry; IdP per-client claim filters that exclude the key; expecting a claim that only premium/specific-audience tokens contain.","solutions":["Verify against an actual decoded token and fix the final segment of the path","Configure the issuer to always include the leaf key in the nested object","Catch with errors.Is(err, errClaimPathNotFound) and map to a 401 with a descriptive message including the failing prefix"],"exampleFix":"// before\nextractClaimValue(claims, \"realm_access.rols\") // typo\n// after\nextractClaimValue(claims, \"realm_access.roles\")","handlingStrategy":"try-catch","validationCode":"perms, ok := claims[\"permissions\"].(map[string]any)\nif !ok { return fmt.Errorf(\"permissions missing or not an object\") }\nif _, ok := perms[\"role\"]; !ok {\n    return fmt.Errorf(\"permissions.role missing from token\")\n}","typeGuard":"func hasLeaf(claims jwt.MapClaims, parent, leaf string) bool {\n    m, ok := claims[parent].(map[string]any)\n    if !ok { return false }\n    _, ok = m[leaf]\n    return ok\n}","tryCatchPattern":"v, err := extractClaimValue(claims, \"permissions.role\")\nif errors.Is(err, errClaimPathNotFound) {\n    // deny by default (403) and record the missing leaf path\n}","preventionTips":["Fail closed: treat missing leaf claims as unauthorized, not as anonymous role","Verify leaf keys exist across all token audiences/flows you accept","Contract-test issuer output so leaf-key removals are caught before rollout"],"tags":["jwt","rbac","claims"],"backgroundTag":"jwt-claim-not-found","analyzedSha":"187eb24962502e91f1fee856230670958b66e89c","analyzedAt":"2026-09-01T20:34:54.554Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}