transloadit/uppy · error · Error

Invalid token payload

Error message

Invalid token payload

What it means

verifyJwtToken runs jwt.verify and then requires the decoded payload to be a non-null object containing a `data` property. A token that verifies cryptographically but lacks the expected { data: ... } shape (or decodes to a primitive/string) throws 'Invalid token payload'.

Source

Thrown at packages/@uppy/companion/src/server/helpers/jwt.ts:39

// there's no way for them to retry their failed files.
// With 400 days, there's still a theoretical possibility but very low.
export const MAX_AGE_REFRESH_TOKEN = 60 * 60 * 24 * 400
export const MAX_AGE_24H = 60 * 60 * 24

type EncryptionSecret = string | Buffer

const generateToken = (
  data: unknown,
  secret: EncryptionSecret,
  maxAge: number,
): string => {
  return jwt.sign({ data }, secret, { expiresIn: maxAge })
}

const verifyJwtToken = (token: string, secret: EncryptionSecret) => {
  const decoded = jwt.verify(token, secret, {})
  if (!decoded || typeof decoded !== 'object' || !('data' in decoded)) {
    throw new Error('Invalid token payload')
  }
  return decoded['data']
}

export const generateEncryptedToken = (
  payload: unknown,
  secret: EncryptionSecret,
  maxAge = MAX_AGE_24H,
): string => {
  // return payload // for easier debugging
  return encrypt(generateToken(payload, secret, maxAge), secret)
}

export const generateEncryptedAuthToken = (
  payload: unknown,
  secret: EncryptionSecret,
  maxAge?: number,
): string => {

View on GitHub (pinned to 5d4dedd02a)

Solutions

  1. Use the library's own token generators (generateToken/generateEncryptedToken) instead of hand-signing JWTs
  2. Ensure the signed payload wraps data as { data: ... }
  3. Check for mixed Uppy versions between token producer and consumer

Example fix

// before
const token = jwt.sign({ userId: 1 }, secret)

// after
import { generateToken } from '../helpers/jwt'
const token = generateToken({ userId: 1 }, secret) // signs { data: { userId: 1 } }
Defensive patterns

Strategy: try-catch

Validate before calling

import jwt from 'jsonwebtoken'
const shapeOk = (token: string, secret: string) => {
  const d = jwt.decode(token)
  return typeof d === 'object' && d !== null && 'data' in d
}

Type guard

const hasDataPayload = (d: unknown): d is { data: unknown } =>
  typeof d === 'object' && d !== null && 'data' in d;

Try / catch

try { verifyEncryptedToken(token, secret) } catch (err) {
  if (err.message === 'Invalid token payload') { /* regenerate token with proper helpers */ }
}

Prevention

When it happens

Trigger: Passing a JWT that was signed by the same secret but with a different payload schema (e.g. { foo: 1 } or a plain string payload) to endpoints that call verifyJwtToken/verifyEncryptedToken.

Common situations: Custom code signing its own tokens with companion's secret, version drift where token payload format changed, or accidentally sending an unrelated JWT (auth token) where an uppy token is expected.

Understand the failure class

Related errors


AI-assisted analysis of transloadit/uppy@5d4dedd02a (2026-08-28). Data as JSON: /api/errors/c9e130509b4f8224. Report an issue: GitHub.