honojs/hono · error · JwtPayloadRequiresAud

required "aud" in jwt payload: ${JSON.stringify(payload)}

Error message

required "aud" in jwt payload: ${JSON.stringify(payload)}

What it means

Thrown when audience (aud) validation is requested via the aud option but the token payload contains no aud claim. The library requires the claim to be present before it can attempt matching.

Source

Thrown at src/utils/jwt/jwt.ts:160

    if (typeof payload.iat !== 'number' || !Number.isFinite(payload.iat) || now < payload.iat) {
      throw new JwtTokenIssuedAt(now, payload.iat)
    }
  }
  if (iss) {
    if (!payload.iss) {
      throw new JwtTokenIssuer(iss, null)
    }
    if (typeof iss === 'string' && payload.iss !== iss) {
      throw new JwtTokenIssuer(iss, payload.iss)
    }
    if (iss instanceof RegExp && !iss.test(payload.iss)) {
      throw new JwtTokenIssuer(iss, payload.iss)
    }
  }

  if (aud) {
    if (!payload.aud) {
      throw new JwtPayloadRequiresAud(payload)
    }

    const audiences = Array.isArray(payload.aud) ? payload.aud : [payload.aud]
    const matched = audiences.some((payloadAud): boolean =>
      aud instanceof RegExp
        ? aud.test(payloadAud)
        : typeof aud === 'string'
          ? payloadAud === aud
          : Array.isArray(aud) && aud.includes(payloadAud)
    )
    if (!matched) {
      throw new JwtTokenAudience(aud, payload.aud)
    }
  }

  const headerPayload = token.substring(0, token.lastIndexOf('.'))
  const verified = await verifying(
    publicKey,

View on GitHub (pinned to e2740d5a1b)

Solutions

  1. Decode the token and confirm whether aud exists and what value it holds
  2. Configure your API as an audience/scope in your IdP so tokens include aud
  3. Set the aud option to the value your IdP actually emits
  4. Remove the aud option if audience validation is unnecessary for this token type

Example fix

// before
await verify(token, key, { aud: 'https://api.example.com' }) // token has no aud
// after
await verify(token, key, {}) // or configure IdP to emit aud: 'https://api.example.com'
Defensive patterns

Strategy: validation

Validate before calling

const payload = decodePayload(token)
if (!('aud' in payload)) throw new BadRequest('token missing aud')

Type guard

const hasAud = (p: unknown): p is { aud: string | string[] } =>
  typeof p === 'object' && p !== null && 'aud' in p

Prevention

When it happens

Trigger: verify(token, key, { aud: 'my-api' }) or verifyWithJwks with verification.aud set, and the decoded payload has no aud field (JwtPayloadRequiresAud).

Common situations: ID tokens (which target a client_id, sometimes absent) verified as access tokens; audience not configured in the IdP for your API; custom tokens minted without aud; passing aud option when the token type never carries it.

Related errors


AI-assisted analysis of honojs/hono@e2740d5a1b (2026-08-28). Data as JSON: /api/errors/83e19e74b6876000. Report an issue: GitHub.