quarkusio/quarkus · error · io.quarkus.oidc.runtime.OIDCException
Claim value at path '%s' is not a string
Error message
Claim value at path '%s' is not a string
What it means
Quarkus OIDC's OidcUtils.findStringClaimValue throws OIDCException when a token claim located at the given path exists but its value is not a JSON string. Code expecting a string claim (e.g. 'sub', 'preferred_username') receives a number, boolean, array, or object instead.
Source
Thrown at extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcUtils.java:337
return Arrays.asList(claimValue.toString().split(sep));
} else {
return Collections.emptyList();
}
}
private static String[] splitClaimPath(String claimPath) {
return claimPath.indexOf('/') > 0 ? CLAIM_PATH_PATTERN.split(claimPath) : new String[] { claimPath };
}
static String findStringClaimValue(String claimPath, JsonObject json) {
Object value = findClaimValue(claimPath, json, splitClaimPath(claimPath), 0);
if (value == null) {
return null;
}
if (value instanceof String) {
return (String) value;
}
throw new OIDCException("Claim value at path '" + claimPath + "' is not a string");
}
private static Object findClaimValue(String claimPath, JsonObject json, String[] pathArray, int step) {
Object claimValue = json.getValue(pathArray[step].replace("\"", ""));
if (claimValue == null) {
LOG.debugf("No claim exists at the path '%s' at the path segment '%s'", claimPath, pathArray[step]);
} else if (step + 1 < pathArray.length) {
if (claimValue instanceof JsonObject) {
int nextStep = step + 1;
return findClaimValue(claimPath, (JsonObject) claimValue, pathArray, nextStep);
} else {
LOG.debugf("Claim value at the path '%s' is not a json object", claimPath);
}
}
return claimValue;
}
View on GitHub (pinned to e1c734241f)
Solutions
- Fix the claim path configuration so it points to an actual string claim in the token
- Transform the token at the identity provider so the claim is emitted as a string (e.g. 'sub' as string)
- Use a claim-value accessor that handles non-string JSON types instead of findStringClaimValue
Example fix
// before: 'sub': 12345 (number) -> OIDCException // after: configure IdP or mapping so 'sub': "12345" (string)
Defensive patterns
Strategy: type-guard
Validate before calling
Object claim = jwtJson.getJson("claimPath");
if (!(claim instanceof String)) throw new IllegalArgumentException("Claim must be a string: " + claim); Type guard
boolean isStringClaim(Object v) { return v instanceof String; } Try / catch
try { value = findStringClaimValue(token, claimPath); } catch (OIDCException e) { log.warn("Claim {} not a string, falling back", claimPath); value = String.valueOf(findClaimValue(...)); } Prevention
- Inspect decoded tokens (jwt.io) before wiring claim paths
- Configure the IdP to emit string claims (e.g. string 'sub')
- Write a startup test decoding a sample token and asserting claim types
When it happens
Trigger: Calling findStringClaimValue (or configured claim paths like name/subject claim paths) on a token where the claim at claimPath holds a non-string JSON value (e.g. an integer 'sub', a JSON object), so the instanceof String check fails and OIDCException is thrown.
Common situations: IdP-issued tokens with numeric 'sub' claims (some providers use integers); custom claim mappings pointing at nested objects or arrays; misconfigured quarkus.oidc token.claim-path settings pointing at the wrong claim.
Related errors
- Json array ended without ]
- Control characters not allowed in json string
- String not closed
- Unable to read json constant for: %s
- Unable to parse: ${resolvedModelPath}
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/c1bd77db625b246c.
Report an issue: GitHub.