{"record":{"id":"c9e130509b4f8224","repo":"transloadit/uppy","slug":"invalid-token-payload","errorCode":null,"errorMessage":"Invalid token payload","messagePattern":"Invalid token payload","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@uppy/companion/src/server/helpers/jwt.ts","lineNumber":39,"sourceCode":"// there's no way for them to retry their failed files.\n// With 400 days, there's still a theoretical possibility but very low.\nexport const MAX_AGE_REFRESH_TOKEN = 60 * 60 * 24 * 400\nexport const MAX_AGE_24H = 60 * 60 * 24\n\ntype EncryptionSecret = string | Buffer\n\nconst generateToken = (\n  data: unknown,\n  secret: EncryptionSecret,\n  maxAge: number,\n): string => {\n  return jwt.sign({ data }, secret, { expiresIn: maxAge })\n}\n\nconst verifyJwtToken = (token: string, secret: EncryptionSecret) => {\n  const decoded = jwt.verify(token, secret, {})\n  if (!decoded || typeof decoded !== 'object' || !('data' in decoded)) {\n    throw new Error('Invalid token payload')\n  }\n  return decoded['data']\n}\n\nexport const generateEncryptedToken = (\n  payload: unknown,\n  secret: EncryptionSecret,\n  maxAge = MAX_AGE_24H,\n): string => {\n  // return payload // for easier debugging\n  return encrypt(generateToken(payload, secret, maxAge), secret)\n}\n\nexport const generateEncryptedAuthToken = (\n  payload: unknown,\n  secret: EncryptionSecret,\n  maxAge?: number,\n): string => {","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/transloadit/uppy/blob/5d4dedd02a1ac0ae022c75c54aca76558f88e256/packages/@uppy/companion/src/server/helpers/jwt.ts#L21-L57","documentation":"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'.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Use the library's own token generators (generateToken/generateEncryptedToken) instead of hand-signing JWTs","Ensure the signed payload wraps data as { data: ... }","Check for mixed Uppy versions between token producer and consumer"],"exampleFix":"// before\nconst token = jwt.sign({ userId: 1 }, secret)\n\n// after\nimport { generateToken } from '../helpers/jwt'\nconst token = generateToken({ userId: 1 }, secret) // signs { data: { userId: 1 } }","handlingStrategy":"try-catch","validationCode":"import jwt from 'jsonwebtoken'\nconst shapeOk = (token: string, secret: string) => {\n  const d = jwt.decode(token)\n  return typeof d === 'object' && d !== null && 'data' in d\n}","typeGuard":"const hasDataPayload = (d: unknown): d is { data: unknown } =>\n  typeof d === 'object' && d !== null && 'data' in d;","tryCatchPattern":"try { verifyEncryptedToken(token, secret) } catch (err) {\n  if (err.message === 'Invalid token payload') { /* regenerate token with proper helpers */ }\n}","preventionTips":["Only mint tokens with the library's generate* helpers","Keep token producer and consumer on the same Uppy version"],"tags":["companion","jwt","token","payload"],"backgroundTag":"jwt-payload-shape-invalid","analyzedSha":"5d4dedd02a1ac0ae022c75c54aca76558f88e256","analyzedAt":"2026-08-28T12:18:41.267Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}