{"record":{"id":"9955a5d6ffa365d7","repo":"gofr-dev/gofr","slug":"document-id-cannot-be-empty","errorCode":null,"errorMessage":"document ID cannot be empty","messagePattern":"document ID cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/gofr/datasource/elasticsearch/elasticsearch.go","lineNumber":26,"sourceCode":"\t\"fmt\"\n\t\"strings\"\n\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.","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/gofr-dev/gofr/blob/187eb24962502e91f1fee856230670958b66e89c/pkg/gofr/datasource/elasticsearch/elasticsearch.go#L8-L44","documentation":"The bracketed segment must be a numeric index; extractArrayClaim parses it with fmt.Sscanf(\"%d\"). If parsing fails (non-numeric or empty inside brackets) it wraps errInvalidArrayIndex with the offending fragment. This guarantees the array notation refers to an actual positional element.","triggerScenarios":"Paths like \"roles[]\", \"roles[abc]\", \"roles[first]\"; dynamic index strings built from user input or config that weren't converted to integers.","commonSituations":"Using a named key where an index is required (wanting roles[admin] instead of nested claims); config value stored as a string enum instead of a number; copying dot-notation JSON-path habits into this simpler syntax.","solutions":["Use a numeric zero-based index, e.g. \"roles[0]\"","If you need key-based access, use dotted nested-path syntax (\"claims.roles.primary\") rather than bracket notation","Sanitize/atoi the index at config load time so invalid values fail at boot, not per-request"],"exampleFix":"// before\nextractClaimValue(claims, \"roles[admin]\")\n// after\nextractClaimValue(claims, \"roles[0]\")","handlingStrategy":"validation","validationCode":"idxStr := strings.Trim(strings.SplitN(path, \"[\", 2)[1], \"]\")\nif _, err := strconv.Atoi(idxStr); err != nil {\n    return fmt.Errorf(\"claim path index must be numeric: %q\", idxStr)\n}","typeGuard":null,"tryCatchPattern":"v, err := extractClaimValue(claims, path)\nif errors.Is(err, errInvalidArrayIndex) {\n    // correct to numeric index before retrying\n}","preventionTips":["Use zero-based numeric indices only","Convert config values to int at load time (strconv.Atoi) so bad values fail at boot","Never interpolate non-numeric strings into the bracket position"],"tags":["jwt","rbac","parsing"],"backgroundTag":"invalid-claim-path-syntax","analyzedSha":"187eb24962502e91f1fee856230670958b66e89c","analyzedAt":"2026-09-01T20:34:54.554Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}