quarkusio/quarkus · error · SpiffeConnectionException
JWT-SVID 'aud' claim is not a string or array of strings
Error message
JWT-SVID 'aud' claim is not a string or array of strings
What it means
The 'aud' claim must be either a single string or an array of strings. Any other JSON type (number, object, boolean, null handled separately) makes the token unparseable as a valid audience set, so SpiffeConnectionException is thrown.
Source
Thrown at extensions/spiffe-client/runtime/src/main/java/io/quarkus/spiffe/client/runtime/internal/SpiffeClientImpl.java:253
Object aud = payload.getValue("aud");
if (aud == null) {
throw new SpiffeConnectionException("JWT-SVID from SPIRE agent is missing the required 'aud' claim");
}
final Set<String> audience;
if (aud instanceof JsonArray audienceAsArray) {
audience = new HashSet<>(audienceAsArray.size());
for (int i = 0; i < audienceAsArray.size(); i++) {
if (audienceAsArray.getValue(i) instanceof String audienceAsString) {
audience.add(audienceAsString);
} else {
throw new SpiffeConnectionException(
"JWT-SVID 'aud' array element at index " + i + " is not a string:" + audienceAsArray.getValue(i));
}
}
} else if (aud instanceof String audienceAsString) {
audience = Set.of(audienceAsString);
} else {
throw new SpiffeConnectionException(
"JWT-SVID 'aud' claim is not a string or array of strings");
}
if (!audience.containsAll(requestedAudiences)) {
throw new SpiffeConnectionException(
"JWT-SVID 'aud' claim does not contain the requested audiences; requested: "
+ requestedAudiences + ", received: " + audience);
}
if (audience.size() != requestedAudiences.size()) {
throw new SpiffeConnectionException(
"JWT-SVID 'aud' claim contains unexpected extra audiences; requested: "
+ requestedAudiences + ", received: " + audience);
}
Long exp = payload.getLong("exp");
if (exp == null) {
throw new SpiffeConnectionException("JWT-SVID from SPIRE agent is missing the required 'exp' claim");
}
Instant expiry = Instant.ofEpochSecond(exp);View on GitHub (pinned to e1c734241f)
Solutions
- Fix the token producer so aud is a string or array of strings
- Use real SPIRE-issued JWT-SVIDs instead of synthetic ones
- Validate token payloads with a JWT linter before injecting them into tests
Example fix
// before
{"aud": 12345}
// after
{"aud": "https://api.example.com"} Defensive patterns
Strategy: type-guard
Type guard
static boolean audTypeOk(Object aud) {
return aud instanceof String || aud instanceof JsonArray;
} Try / catch
try {
return spiffeClient.getWorkloadJsonWebToken(audiences).await().indefinitely();
} catch (SpiffeConnectionException e) {
if (e.getMessage().contains("not a string or array of strings")) {
// fix token serialization
}
throw e;
} Prevention
- Serialize aud as string or array of strings per RFC 7519
- Validate generated tokens with a JWT library before injecting into tests
- Avoid building JWT payload JSON by hand
When it happens
Trigger: Payload contains aud as a non-string, non-array JSON value, e.g. aud: 123 or aud: {"x":1} in a stubbed or corrupted token.
Common situations: Hand-crafted test tokens with wrong claim types; scripts that build JWT payloads programmatically with incorrect serialization.
Related errors
- JWT-SVID 'aud' array element at index ${i} is not a string:$
- JWT-SVID 'aud' claim does not contain the requested audience
- JWT-SVID 'aud' claim contains unexpected extra audiences; re
- 'credentials.jwt.source' is set to 'spiffe-jwt', but no audi
- JWT-SVID from SPIRE agent has no token
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/0b1d392d094e4373.
Report an issue: GitHub.