gofr-dev/gofr · error
claim value is not an array
Error message
claim value is not an array
What it means
errClaimValueNotArray is returned by extractArrayClaim when the claim exists in the JWT but its value is not a JSON array ([]any). Array notation like "roles[0]" only works when the claim holds a list; a string, map, or scalar at that key triggers this error. It indicates the claim-path shape does not match the token's actual claim structure.
Source
Thrown at pkg/gofr/rbac/middleware.go:68
errJWTClaimsNotFound = errors.New("JWT claims not found in request context")
// errEmptyClaimPath is returned when claim path is empty.
errEmptyClaimPath = errors.New("empty claim path")
// errClaimPathNotFound is returned when a claim path is not found in JWT claims.
errClaimPathNotFound = errors.New("claim path not found")
// errInvalidArrayNotation is returned when array notation is invalid.
errInvalidArrayNotation = errors.New("invalid array notation")
// errInvalidArrayIndex is returned when array index is invalid.
errInvalidArrayIndex = errors.New("invalid array index")
// errClaimKeyNotFound is returned when a claim key is not found.
errClaimKeyNotFound = errors.New("claim key not found")
// errClaimValueNotArray is returned when a claim value is not an array.
errClaimValueNotArray = errors.New("claim value is not an array")
// errArrayIndexOutOfBounds is returned when array index is out of bounds.
errArrayIndexOutOfBounds = errors.New("array index out of bounds")
// errInvalidClaimStructure is returned when claim structure is invalid.
errInvalidClaimStructure = errors.New("invalid claim structure")
// errAuthorizationError is returned as a generic error message for unknown errors in traces.
errAuthorizationError = errors.New("authorization error")
)
// Middleware creates an HTTP middleware function that enforces RBAC authorization.
// It extracts the user's role and checks if the role is allowed for the requested route.
//
//nolint:gocognit,gocyclo // Middleware complexity is acceptable due to multiple authorization paths
func Middleware(config *Config) func(handler http.Handler) http.Handler {
return func(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {View on GitHub (pinned to 187eb24962)
Solutions
- Inspect the decoded token and align JWTClaimPath with the actual value type: use a plain key path ("role") for strings, or navigate maps with dot notation ("realm_access.roles[0]").
- Ask the identity provider to always emit the claim as an array (multi-valued mapper) so the shape is stable.
- If the claim can legitimately be either string or array, handle both in a custom ErrorHandler or pre-normalize tokens.
- Update config when migrating IdPs — claim shapes rarely match one-to-one.
Example fix
// before (token has "role": "admin", a string) config.JWTClaimPath = "role[0]" // after config.JWTClaimPath = "role"
Defensive patterns
Strategy: type-guard
Validate before calling
func rolesIsArray(claims jwt.MapClaims, key string) bool {
_, ok := claims[key].([]any)
return ok
}
// startup check against a sample token:
// if !rolesIsArray(sampleClaims, "roles") { log.Fatal("claim is not an array; use plain/dot path") } Type guard
func isArrayClaim(v any) bool {
_, ok := v.([]any)
return ok
} Try / catch
if err != nil && strings.Contains(err.Error(), "claim value is not an array") {
logger.Warn("claim shape mismatch; adjust JWTClaimPath (string vs array)", "err", err)
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
} Prevention
- Check the claim's JSON type in a decoded token before choosing array notation
- Make the IdP emit role claims as arrays consistently (multi-valued mapper)
- Re-verify claim shapes after any IdP migration or client change
When it happens
Trigger: JWTClaimPath "roles[0]" while the token contains "roles": "admin" (a plain string) or "roles": {"admin": true} (a map); extractArrayClaim's type assertion value.([]any) fails and the error is returned with the offending key name.
Common situations: Identity provider emits role as a single string for users with one role but as an array for multiple roles; switching IdPs where the equivalent claim is a map of role->bool (Keycloak realm_access.roles vs resource_access); path written for one token shape reused against another client's tokens.
Related errors
- claim key not found
- array index out of bounds
- invalid claim structure
- failed to extract role from JWT: %w
- %w: %s
AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01).
Data as JSON: /api/errors/d3ad906735a16a14.
Report an issue: GitHub.