transloadit/uppy · error · Error

Invalid token payload: expected string

Error message

Invalid token payload: expected string

What it means

verifyEncryptedAuthToken expects the decrypted token payload (the `data` inside the JWT) to be a JSON string that can be parsed into a provider-token map. If the payload is present but not a string, it throws 'Invalid token payload: expected string'.

Source

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

}

export const verifyEncryptedToken = (
  token: string,
  secret: EncryptionSecret,
) => {
  const ret = verifyJwtToken(decrypt(token, secret), secret)
  if (!ret) throw new Error('No payload')
  return ret
}

export const verifyEncryptedAuthToken = <T extends Record<string, unknown>>(
  token: string,
  secret: EncryptionSecret,
  providerName: string,
): T => {
  const json = verifyEncryptedToken(token, secret)
  if (typeof json !== 'string') {
    throw new Error('Invalid token payload: expected string')
  }
  const tokens: T = JSON.parse(json)
  if (!isRecord(tokens) || !Object.hasOwn(tokens, providerName))
    throw new Error(`Missing token payload for provider ${providerName}`)
  return tokens
}

function getCommonCookieOptions({
  companionOptions,
}: {
  companionOptions: CompanionRuntimeOptions
}): Record<string, unknown> {
  const cookieOptions: Record<string, unknown> = {
    httpOnly: true,
  }

  // Fix to show thumbnails on Chrome
  // https://community.transloadit.com/t/dropbox-and-box-thumbnails-returning-401-unauthorized/15781/2

View on GitHub (pinned to 5d4dedd02a)

Solutions

  1. Generate tokens with the provided helpers so the payload is JSON.stringify'd
  2. If generating manually: generateEncryptedToken(JSON.stringify(tokens), secret)
  3. Regenerate affected tokens after fixing the producer

Example fix

// before
const token = generateEncryptedToken(tokens, secret) // object payload

// after
const token = generateEncryptedToken(JSON.stringify(tokens), secret)
Defensive patterns

Strategy: type-guard

Validate before calling

const token = generateEncryptedToken(JSON.stringify(tokens), secret)

Type guard

const isJsonString = (v: unknown): v is string => typeof v === 'string';

Try / catch

try { verifyEncryptedAuthToken(token, secret, 'dropbox') } catch (err) {
  if (err.message === 'Invalid token payload: expected string') { /* re-mint token with stringified payload */ }
}

Prevention

When it happens

Trigger: Passing an uppy auth token whose data was stored as an object/number rather than a JSON.stringify'd string — e.g. custom code called generateEncryptedToken(obj, secret) instead of generateEncryptedToken(JSON.stringify(obj), secret).

Common situations: Hand-rolled token generation that skips the stringify step, or tokens produced by a differently-implemented helper in another service sharing the secret.

Understand the failure class

Related errors


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