hashicorp/nomad · error
value %v in %q list claim could not be parsed as string
Error message
value %v in %q list claim could not be parsed as string
What it means
extractListMappings converted the claim to a list, but one element inside it has a type stringifyClaimValue cannot stringify (e.g. a nested map/object element). The whole list extraction fails for that mapping.
Source
Thrown at lib/auth/claims.go:115
all map[string]interface{}, mappings map[string]string) (map[string][]string, error) {
result := make(map[string][]string)
for source, target := range mappings {
rawValue := getClaim(all, source)
if rawValue == nil {
continue
}
rawList, ok := normalizeList(rawValue)
if !ok {
return nil, fmt.Errorf("%q list claim could not be converted to string list", source)
}
list := make([]string, 0, len(rawList))
for _, raw := range rawList {
value, ok := stringifyClaimValue(raw)
if !ok {
return nil, fmt.Errorf("value %v in %q list claim could not be parsed as string",
raw, source)
}
if value == "" {
continue
}
list = append(list, value)
}
result[target] = list
}
return result, nil
}
// getClaim returns a claim value from allClaims given a provided claim string.
// If this string is a valid JSONPointer, it will be interpreted as such to
// locate the claim. Otherwise, the claim string will be used directly.View on GitHub (pinned to 482b49bf1a)
Solutions
- Use a JSON pointer to the scalar field within each element if the provider supports it (often not possible for arrays of objects) — otherwise expose a flat string array claim at the IdP
- Configure a transformer/mapper at the IdP (e.g. Keycloak token mapper) to emit a plain array of strings
- Identify the offending element from the %v value printed in the error
Example fix
// IdP emits [{"name":"admin"},{"name":"reader"}]
// after: mapper emits ["admin","reader"]
ListClaimMappings: {"/groups": "groups"} Defensive patterns
Strategy: type-guard
Validate before calling
func allElementsScalar(arr []interface{}) bool {
for _, e := range arr {
switch e.(type) {
case string, bool, float64:
default:
return false
}
}
return true
} Type guard
func elemAsString(e interface{}) (string, bool) {
s, ok := e.(string)
return s, ok
} Try / catch
if err != nil && strings.Contains(err.Error(), "could not be parsed as string") {
return fmt.Errorf("list claim contains non-scalar element: %w", err)
} Prevention
- Configure the IdP token mapper to emit arrays of plain strings (e.g. group names, not group objects)
- Spot-check decoded tokens for nested objects inside list claims
- Document the expected claim schema for each IdP integration
When it happens
Trigger: A list claim containing non-scalar entries, e.g. roles as array of objects [{"name":"admin"}] mapped directly via ListClaimMappings.
Common situations: Array-of-objects claims from enterprise IdPs (groups as [{id, name}]); mixed-type arrays where one entry is a JSON object.
Related errors
- %q list claim could not be converted to string list
- error converting claim '%s' to string from unknown type %T
- no signed workload identity available
- JWT login returned an empty secret
- JWT login did not return a token
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/c11615424dada971.
Report an issue: GitHub.