apereo/cas · error · IllegalArgumentException
JWT string claim is missing or invalid
Error message
JWT string claim is missing or invalid
What it means
requiredStringClaim extracts a named JWT claim and requires it to be a non-blank String. Called by issuer, credentialType, clientId, and validateKeyBindingJwt, it throws IllegalArgumentException when the claim is missing, not a string, or blank.
Solutions
- Add the required claim with a non-blank string value before signing the JWT
- Check which claim failed (iss/clientId/credentialType) via the call site and inspect the token payload in a JWT decoder
- Fix client configuration that leaves the claim empty (e.g. unconfigured client_id)
Example fix
// before
claims.setStringClaim("client_id", ""); // blank
// after
claims.setStringClaim("client_id", "my-client"); // non-blank string Defensive patterns
Strategy: validation
Validate before calling
boolean hasClaim(Map<String,Object> claims, String name) {
Object v = claims.get(name);
return v instanceof String s && !s.isBlank();
} Prevention
- Check required claim presence before signing JWTs
- Avoid blank-string defaults in client config
- Log claim names during development to catch typos
When it happens
Trigger: Key-binding JWT or credential-response JWT lacks a required claim (iss, credential type, client_id, nonce, etc.), or the claim value is null, a non-string type, or an empty/whitespace string.
Common situations: Clients omitting required claims when building the key-binding JWT; empty-string claims from misconfigured clients; claim name typos producing null lookups.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- JWT audience is invalid
- JWT time claim is invalid
- Resource ID already exists in namespace .
- Username is null.
- Password is null.
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/7dbd0790626aedce.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-oidc-vc/src/main/java/org/apereo/cas/vc/presentation/OidcVerifiableCredentialPresentationResponseEndpointController.java:470
}
}
private static List<String> readAudience(final Map<String, Object> claims) {
val audience = claims.get("aud");
if (audience instanceof final String value) {
return List.of(value);
}
if (audience instanceof final List<?> values
&& values.stream().allMatch(String.class::isInstance)) {
return values.stream().map(String.class::cast).toList();
}
throw new IllegalArgumentException("JWT audience is invalid");
}
private static String requiredStringClaim(final Map<String, Object> claims, final String name) {
val value = claims.get(name);
if (!(value instanceof final String stringValue) || stringValue.isBlank()) {
throw new IllegalArgumentException("JWT string claim is missing or invalid");
}
return stringValue;
}
private static boolean constantTimeEquals(final String left, final String right) {
return MessageDigest.isEqual(left.getBytes(StandardCharsets.UTF_8), right.getBytes(StandardCharsets.UTF_8));
}
private static ResponseEntity<Map<String, Object>> buildResponse(final HttpStatus status,
final Map<String, Object> body) {
return ResponseEntity.status(status)
.cacheControl(CacheControl.noStore())
.header(HttpHeaders.PRAGMA, "no-cache")
.body(body);
}
private static void require(final boolean condition, final String message) {
if (!condition) {View on GitHub (pinned to e7288fc434)