quarkusio/quarkus · error · SpiffeConnectionException

JWT-SVID 'aud' array element at index ${i} is not a string:$

Error message

JWT-SVID 'aud' array element at index ${i} is not a string:${value}

What it means

When the 'aud' claim is a JSON array, every element must be a string per JWT spec. The client iterates the array and throws SpiffeConnectionException at the first non-string element, since audiences must be comparable to the requested set of strings.

Source

Thrown at extensions/spiffe-client/runtime/src/main/java/io/quarkus/spiffe/client/runtime/internal/SpiffeClientImpl.java:246

        String sub = payload.getString("sub");
        SpiffeValidator.validateSpiffeId(sub);
        if (!sub.equals(svid.getSpiffeId())) {
            throw new SpiffeConnectionException(
                    "JWT-SVID proto SPIFFE ID does not match the 'sub' claim; proto: " + svid.getSpiffeId() + ", sub: " + sub);
        }

        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);

View on GitHub (pinned to e1c734241f)

Solutions

  1. Correct the token source so all aud array elements are strings
  2. Replace stubbed JWTs with real ones fetched via spire-agent api fetch jwt
  3. Check for middleware/proxies that decode and re-encode JWT payloads with altered types

Example fix

// before
{"aud":["https://api.example.com", 42]}
// after
{"aud":["https://api.example.com", "https://other.example.com"]}
Defensive patterns

Strategy: type-guard

Type guard

static boolean audClaimIsValid(Object aud) {
    if (aud instanceof String) return true;
    if (aud instanceof JsonArray arr) {
        for (int i = 0; i < arr.size(); i++) {
            if (!(arr.getValue(i) instanceof String)) return false;
        }
        return true;
    }
    return false;
}

Try / catch

try {
    return spiffeClient.getWorkloadJsonWebToken(audiences).await().indefinitely();
} catch (SpiffeConnectionException e) {
    if (e.getMessage().contains("'aud' array element")) {
        // fix token producer / replace stubs
    }
    throw e;
}

Prevention

When it happens

Trigger: Decoded payload contains aud as an array with numeric/boolean/object/null elements — typically from a hand-built or corrupted token rather than a real SPIRE-issued SVID.

Common situations: Test fixtures with wrongly typed audience values; JSON encoding mistakes when replaying captured tokens; intermediary services rewriting the token payload.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/5894aed50669cb2f. Report an issue: GitHub.