{"record":{"id":"ac72019c6703c6c8","repo":"transloadit/uppy","slug":"invalid-request-body-ac7201","errorCode":null,"errorMessage":"Invalid request body","messagePattern":"Invalid request body","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"packages/@uppy/companion/src/server/controllers/googlePicker.ts","lineNumber":36,"sourceCode":"    accessToken: z.string().min(1),\n    fileId: z.string().min(1),\n  }),\n  z.object({\n    platform: z.literal('photos'),\n    accessToken: z.string().min(1),\n    url: z.string().min(1),\n  }),\n])\n\nconst get = async (req: Request, res: Response): Promise<void> => {\n  try {\n    logger.debug('Google Picker file import handler running', undefined, req.id)\n\n    const allowLocalUrls = false\n\n    const parsedBody = googlePickerBodySchema.safeParse(req.body)\n    if (!parsedBody.success) {\n      res.status(400).json({ error: 'Invalid request body' })\n      return\n    }\n    const { accessToken, platform } = parsedBody.data\n\n    if (\n      platform === 'photos' &&\n      !validateURL(parsedBody.data.url, allowLocalUrls)\n    ) {\n      res.status(400).json({ error: 'Invalid URL' })\n      return\n    }\n\n    const download = () => {\n      if (platform === 'drive') {\n        return streamGoogleFile({\n          token: accessToken,\n          id: parsedBody.data.fileId,\n        })","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/transloadit/uppy/blob/5d4dedd02a1ac0ae022c75c54aca76558f88e256/packages/@uppy/companion/src/server/controllers/googlePicker.ts#L18-L54","documentation":"Companion's Google Picker import endpoint validates req.body against googlePickerBodySchema (zod). On parse failure it immediately responds 400 'Invalid request body', meaning the payload doesn't match the expected shape (accessToken, platform, etc.).","triggerScenarios":"POSTing to the google-picker endpoint with missing/incorrectly-typed fields — e.g. missing accessToken, platform not in the allowed enum ('photos' vs 'drive'), or a malformed JSON body.","commonSituations":"Client/version mismatch after upgrading @uppy/companion or companion-client (schema changed), hand-rolled fetch calls to the endpoint, or proxies stripping/mangling the JSON body.","solutions":["Ensure the client uses @uppy/google-drive (or companion-client) of a matching version as the Companion server","Send the exact expected body: { accessToken: string, platform: 'photos'|'drive', ... } as application/json","Inspect the zod schema in companion source (googlePickerBodySchema) for the authoritative field list"],"exampleFix":"// before\nfetch('/companion/google-picker', {\n  method: 'POST',\n  body: JSON.stringify({ token: accessToken }),\n})\n\n// after\nfetch('/companion/google-picker', {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json' },\n  body: JSON.stringify({ accessToken, platform: 'drive' }),\n})","handlingStrategy":"validation","validationCode":"const body = { accessToken: token, platform: 'drive' }\nif (typeof body.accessToken === 'string' && body.accessToken && ['drive','photos'].includes(body.platform)) {\n  await fetch(endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) })\n}","typeGuard":"const isValidPickerBody = (b: unknown): b is { accessToken: string; platform: 'drive' | 'photos' } =>\n  typeof b === 'object' && b !== null &&\n  typeof (b as any).accessToken === 'string' && (b as any).accessToken.length > 0 &&\n  ['drive', 'photos'].includes((b as any).platform)","tryCatchPattern":null,"preventionTips":["Pin @uppy/companion and client packages to matching versions","Always send Content-Type: application/json","Read the zod schema in companion source when integrating manually"],"tags":["companion","validation","zod","google-picker","http-400"],"backgroundTag":"schema-validation-failed","analyzedSha":"5d4dedd02a1ac0ae022c75c54aca76558f88e256","analyzedAt":"2026-08-28T12:18:41.267Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}