{"record":{"id":"f2984774a0a22fb1","repo":"transloadit/uppy","slug":"invalid-url","errorCode":null,"errorMessage":"Invalid URL","messagePattern":"Invalid URL","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"packages/@uppy/companion/src/server/controllers/googlePicker.ts","lineNumber":45,"sourceCode":"\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        })\n      }\n      return downloadURL(parsedBody.data.url, allowLocalUrls, req.id, {\n        headers: getAuthHeader(accessToken),\n      })\n    }\n\n    await startDownUpload({ req, res, download, getSize: undefined })\n  } catch (err) {\n    logger.error(err, 'controller.googlePicker.error', req.id)","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/transloadit/uppy/blob/5d4dedd02a1ac0ae022c75c54aca76558f88e256/packages/@uppy/companion/src/server/controllers/googlePicker.ts#L27-L63","documentation":"Companion's Google Picker endpoint rejects the request when the picker result's url field fails validation. Before streaming a 'photos' platform file, Companion validates the URL (including blocking local/internal URLs unless allowLocalUrls is enabled). This is a 400 client error.","triggerScenarios":"POST /google-picker/get with platform === 'photos' and a missing, malformed, or non-URL value in data.url; also when url points to localhost/private ranges and allowLocalUrls is false.","commonSituations":"Client sends a Picker response payload that was constructed manually or truncated; forwarding a relative URL; testing against a local URL while allowLocalUrls is not set in Companion options.","solutions":["Verify the client forwards the exact url field from the Google Picker response","If testing with local URLs, enable allowLocalUrls in Companion config (dev only)","Ensure url is an absolute http(s) URL"],"exampleFix":"// before\ndata: { accessToken, platform: 'photos', url: '/some/path' }\n// after\ndata: { accessToken, platform: 'photos', url: 'https://lh3.googleusercontent.com/...' }","handlingStrategy":"validation","validationCode":"function isValidPickerUrl(url, allowLocal = false) {\n  try {\n    const u = new URL(url)\n    if (!['http:', 'https:'].includes(u.protocol)) return false\n    if (!allowLocal && /^(localhost|127\\.|10\\.|192\\.168\\.|172\\.(1[6-9]|2\\d|3[01])\\.)/.test(u.hostname)) return false\n    return true\n  } catch { return false }\n}","typeGuard":"const isNonEmptyString = (v) => typeof v === 'string' && v.length > 0","tryCatchPattern":null,"preventionTips":["Forward the Google Picker response payload unmodified","Validate data.url client-side before POSTing to /google-picker/get","Only enable allowLocalUrls in local development"],"tags":["google-picker","url-validation","companion","bad-request"],"backgroundTag":"url-validation-failed","analyzedSha":"5d4dedd02a1ac0ae022c75c54aca76558f88e256","analyzedAt":"2026-08-28T12:18:41.267Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}