{"record":{"id":"c11615424dada971","repo":"hashicorp/nomad","slug":"value-v-in-q-list-claim-could-not-be-parsed-as-s","errorCode":null,"errorMessage":"value %v in %q list claim could not be parsed as string","messagePattern":"value (.+?) in %q list claim could not be parsed as string","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/auth/claims.go","lineNumber":115,"sourceCode":"\tall map[string]interface{}, mappings map[string]string) (map[string][]string, error) {\n\n\tresult := make(map[string][]string)\n\tfor source, target := range mappings {\n\t\trawValue := getClaim(all, source)\n\t\tif rawValue == nil {\n\t\t\tcontinue\n\t\t}\n\n\t\trawList, ok := normalizeList(rawValue)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"%q list claim could not be converted to string list\", source)\n\t\t}\n\n\t\tlist := make([]string, 0, len(rawList))\n\t\tfor _, raw := range rawList {\n\t\t\tvalue, ok := stringifyClaimValue(raw)\n\t\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"value %v in %q list claim could not be parsed as string\",\n\t\t\t\t\traw, source)\n\t\t\t}\n\n\t\t\tif value == \"\" {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tlist = append(list, value)\n\t\t}\n\n\t\tresult[target] = list\n\t}\n\n\treturn result, nil\n}\n\n// getClaim returns a claim value from allClaims given a provided claim string.\n// If this string is a valid JSONPointer, it will be interpreted as such to\n// locate the claim. Otherwise, the claim string will be used directly.","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/lib/auth/claims.go#L97-L133","documentation":"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.","triggerScenarios":"A list claim containing non-scalar entries, e.g. roles as array of objects [{\"name\":\"admin\"}] mapped directly via ListClaimMappings.","commonSituations":"Array-of-objects claims from enterprise IdPs (groups as [{id, name}]); mixed-type arrays where one entry is a JSON object.","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"],"exampleFix":"// IdP emits [{\"name\":\"admin\"},{\"name\":\"reader\"}]\n// after: mapper emits [\"admin\",\"reader\"]\nListClaimMappings: {\"/groups\": \"groups\"}","handlingStrategy":"type-guard","validationCode":"func allElementsScalar(arr []interface{}) bool {\n    for _, e := range arr {\n        switch e.(type) {\n        case string, bool, float64:\n        default:\n            return false\n        }\n    }\n    return true\n}","typeGuard":"func elemAsString(e interface{}) (string, bool) {\n    s, ok := e.(string)\n    return s, ok\n}","tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"could not be parsed as string\") {\n    return fmt.Errorf(\"list claim contains non-scalar element: %w\", err)\n}","preventionTips":["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"],"tags":["auth","oidc-claims","list-mapping"],"backgroundTag":"claim-type-unsupported","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}