cloudflare/cloudflared · error
aud field is not a string or an array of strings
Error message
aud field is not a string or an array of strings
What it means
jwtPayload.UnmarshalJSON requires the "aud" claim to be either a JSON string or an array of strings. Any other JSON type (number, object, boolean, null) hits the default branch and returns this error, rejecting the token as structurally invalid.
Source
Thrown at token/token.go:96
var audParser struct {
Aud any `json:"aud"`
}
if err := json.Unmarshal(data, &audParser); err != nil {
return err
}
switch aud := audParser.Aud.(type) {
case string:
p.Aud = []string{aud}
case []any:
for _, a := range aud {
s, ok := a.(string)
if !ok {
return errors.New("aud array contains non-string elements")
}
p.Aud = append(p.Aud, s)
}
default:
return errors.New("aud field is not a string or an array of strings")
}
return nil
}
func (p jwtPayload) isExpired() bool {
return int(time.Now().Unix()) > p.Exp
}
const (
lockRetryInterval = 2 * time.Second
lockTimeout = 10 * time.Minute
startTimeTolerance = int64(1000) // milliseconds
)
// acquireLockFile loops until it successfully creates a lock file for the
// given token file path. The lock file is created at tokenPath + ".lock".
//
// On each iteration:View on GitHub (pinned to 2253eeeb25)
Solutions
- Fix the token issuer to emit aud as a string or an array of strings, e.g. "aud": "app-id" or ["app-id"].
- Decode the token payload (base64 JSON) and confirm the aud claim's JSON type before debugging further.
- If the issuer is fixed but cached tokens persist, discard/regenerate the cached tokens.
Example fix
// before: {"aud": 12345}
// after: {"aud": ["12345"]} Defensive patterns
Strategy: validation
Validate before calling
switch payloadMap["aud"].(type) {
case string, []any:
// acceptable shape (array still needs string-element check)
default:
return fmt.Errorf("aud must be a string or array of strings, got %T", payloadMap["aud"])
} Type guard
func hasValidAudShape(v any) bool {
switch t := v.(type) {
case string:
return t != ""
case []any:
return len(t) > 0
default:
return false
}
} Try / catch
p := jwtPayload{}
if err := json.Unmarshal(rawPayload, &p); err != nil {
if strings.Contains(err.Error(), "aud field") {
return fmt.Errorf("token rejected: aud claim must be string or []string: %w", err)
}
return err
} Prevention
- Standardize token minting so aud is always a string or []string claim.
- Never hand-edit JWT payloads; regenerate tokens through the issuing library.
- Validate the payload JSON shape in tests before shipping a new token producer.
When it happens
Trigger: Unmarshalling a JWT payload whose aud claim is not a string or string-array, e.g. "aud": 12345, "aud": {"tenant":"x"}, or "aud": true.
Common situations: Custom token minters that serialize audience as a numeric client ID or nested object, tokens issued by non-standard services, or manually edited/hand-rolled JWTs used in testing.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- aud array contains non-string elements
- metadata JWT aud is empty
- failed to determine if token is FED: %w
- metadata JWT auth_domain validation failed: %w
- metadata JWT type %q is not match
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/19246257f2559296.
Report an issue: GitHub.