cloudflare/cloudflared · error

aud array contains non-string elements

Error message

aud array contains non-string elements

What it means

jwtPayload.UnmarshalJSON accepts an "aud" claim that is either a single string or an array of strings. If the aud value is a JSON array containing any non-string element, unmarshalling fails with this error so malformed tokens are rejected at parse time instead of producing a corrupted Audience field.

Source

Thrown at token/token.go:91

func (p *jwtPayload) UnmarshalJSON(data []byte) error {
	type Alias jwtPayload
	if err := json.Unmarshal(data, (*Alias)(p)); err != nil {
		return err
	}
	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
)

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Fix the token issuer to emit all aud elements as JSON strings (quote numeric IDs).
  2. Inspect the offending token's payload (decode base64 JSON) to find the non-string element and correct it at the source.
  3. If you cannot fix the issuer, pre-validate or rewrite the token payload before passing it to this library.

Example fix

// before (issuer side): "aud": [12345]
// after (issuer side): "aud": ["12345"]
Defensive patterns

Strategy: validation

Validate before calling

audVal, ok := payloadMap["aud"].([]any)
if ok {
    for _, a := range audVal {
        if _, isStr := a.(string); !isStr {
            return fmt.Errorf("aud array contains non-string element: %v", a)
        }
    }
}

Type guard

func isStringArray(v any) bool {
    arr, ok := v.([]any)
    if !ok {
        return false
    }
    for _, a := range arr {
        if _, isStr := a.(string); !isStr {
            return false
        }
    }
    return true
}

Try / catch

p := jwtPayload{}
if err := json.Unmarshal(rawPayload, &p); err != nil {
    return fmt.Errorf("malformed JWT payload (check aud claim types): %w", err)
}

Prevention

When it happens

Trigger: Unmarshalling a JWT payload (or the metadata JWT header/payload) where aud is an array containing numbers, nulls, booleans, or nested objects, e.g. "aud": ["app", 123] or [null].

Common situations: Token issuers that serialize client IDs as numbers instead of strings, hand-crafted or third-party tokens with heterogeneous aud arrays, or misconfigured identity providers emitting numeric account IDs in the audience claim.

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


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/4ee2c9f9a7e7381a. Report an issue: GitHub.