{"record":{"id":"9ebb6e53f7aac1dd","repo":"gofr-dev/gofr","slug":"operations-cannot-be-empty","errorCode":null,"errorMessage":"operations cannot be empty","messagePattern":"operations cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/gofr/datasource/elasticsearch/elasticsearch.go","lineNumber":28,"sourceCode":"\t\"time\"\n\n\tes \"github.com/elastic/go-elasticsearch/v8\"\n\t\"github.com/elastic/go-elasticsearch/v8/esapi\"\n\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","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/gofr-dev/gofr/blob/187eb24962502e91f1fee856230670958b66e89c/pkg/gofr/datasource/elasticsearch/elasticsearch.go#L10-L46","documentation":"The claim exists but is not a JSON array ([]any), so index access is impossible; the library wraps errClaimValueNotArray with the key. JWT libraries decode JSON arrays as []any, so a string, single object, or map where an array is expected triggers this.","triggerScenarios":"Path \"roles[0]\" but claims[\"roles\"] is a string (\"admin\"), a single object, or a map — e.g. the issuer emits a scalar role instead of a list, or a custom serializer produced map[string]string.","commonSituations":"Auth server changed roles from array to single string after a migration; using a JWT library whose claims decode to different Go types; testing with hand-crafted tokens using the wrong shape.","solutions":["Fix the token issuer to emit an array for the claim (e.g. \"roles\": [\"admin\"])","If the value is legitimately scalar, change the claim path to the simple key form (\"roles\") and handle the single value","Pre-validate the token payload shape (assert []any) in tests so mismatches surface before production"],"exampleFix":"// before\n{\"roles\": \"admin\"}\n// after\n{\"roles\": [\"admin\"]}","handlingStrategy":"type-guard","validationCode":"raw, ok := claims[\"roles\"]\nif !ok { return fmt.Errorf(\"roles claim missing\") }\nif _, ok := raw.([]any); !ok {\n    return fmt.Errorf(\"roles claim is not an array\")\n}","typeGuard":"func isArrayClaim(claims jwt.MapClaims, key string) bool {\n    _, ok := claims[key].([]any)\n    return ok\n}","tryCatchPattern":"v, err := extractClaimValue(claims, \"roles[0]\")\nif errors.Is(err, errClaimValueNotArray) {\n    // fall back to scalar handling or reject token\n}","preventionTips":["Ensure the issuer always emits arrays for list-valued claims","Write a token-fixture test asserting the claim's JSON type","If a scalar is valid, accept both shapes and normalize before extraction"],"tags":["jwt","rbac","type-mismatch"],"backgroundTag":"jwt-claim-type-mismatch","analyzedSha":"187eb24962502e91f1fee856230670958b66e89c","analyzedAt":"2026-09-01T20:34:54.554Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}