mastra-ai/mastra · error

Invalid token payload

Error message

Invalid token payload

What it means

getTokenIssuer decodes a JWT and extracts its `iss` claim. This error is thrown when the token decodes to a valid JWT structure but its `payload` component is missing or is not an object — i.e. `decoded.payload` is absent or a non-object value. The library requires a well-formed complete decode ({ complete: true }) with an object payload before it will trust any claim.

Source

Thrown at packages/auth/src/utils.ts:13

import jwt from 'jsonwebtoken';
import jwksClient from 'jwks-rsa';

export type JwtPayload = jwt.JwtPayload;

export async function decodeToken(accessToken: string) {
  const decoded = jwt.decode(accessToken, { complete: true });
  return decoded;
}

export function getTokenIssuer(decoded: jwt.JwtPayload | null) {
  if (!decoded) throw new Error('Invalid token');
  if (!decoded.payload || typeof decoded.payload !== 'object') throw new Error('Invalid token payload');
  if (!decoded.payload.iss) throw new Error('Invalid token header');
  return decoded.payload.iss;
}

export async function verifyHmac(accessToken: string, secret: string) {
  const decoded = jwt.decode(accessToken, { complete: true });

  if (!decoded) throw new Error('Invalid token');

  return jwt.verify(accessToken, secret) as jwt.JwtPayload;
}

export async function verifyJwks(accessToken: string, jwksUri: string) {
  const decoded = jwt.decode(accessToken, { complete: true });

  if (!decoded) throw new Error('Invalid token');

  const client = jwksClient({ jwksUri });

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Inspect the token at jwt.io or jwt.decode to confirm the payload segment exists and is valid base64 JSON
  2. Regenerate the token from your auth provider — do not hand-edit token strings
  3. Verify the correct token is being passed (access token vs API key vs session id)
  4. Confirm no truncation/corruption in env vars or config files storing the token

Example fix

// before
const issuer = getTokenIssuer(tokenFragment); // token truncated, payload missing
// after
const fullToken = await getAccessTokenFromProvider(); // fetch a complete token
const issuer = getTokenIssuer(fullToken);
Defensive patterns

Strategy: validation

Validate before calling

function hasDecodablePayload(token: string): boolean {
  const parts = token.split('.');
  if (parts.length !== 3) return false;
  try {
    const payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString('utf8'));
    return payload !== null && typeof payload === 'object' && !Array.isArray(payload);
  } catch {
    return false;
  }
}
// call getTokenIssuer only if hasDecodablePayload(token)

Type guard

function hasObjectPayload(decoded: jwt.Jwt | null): decoded is jwt.Jwt & { payload: jwt.JwtPayload } {
  return decoded !== null && 'payload' in decoded && typeof decoded.payload === 'object' && decoded.payload !== null;
}

Try / catch

try {
  const issuer = getTokenIssuer(token);
} catch (e) {
  if (e instanceof Error && e.message === 'Invalid token payload') {
    // token structurally incomplete: re-fetch/refresh the token
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling getTokenIssuer(accessToken) where jwt.decode(accessToken, { complete: true }) returns { header } with no payload, or payload is a string/number instead of an object — typically a hand-crafted, truncated, or corrupted token whose payload segment is empty or malformed base64.

Common situations: Tokens truncated during copy/paste (payload segment cut off), tokens manually assembled for testing, env vars holding stale or corrupted values, or a token that is a JWS with empty payload ('ey...hbGci....e30').

Understand the failure class

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/96ad1db43bf07593. Report an issue: GitHub.