{"record":{"id":"290d5187898ac059","repo":"transloadit/uppy","slug":"failed-to-list-folder-contents-for-doc-name","errorCode":null,"errorMessage":"Failed to list folder contents for '${doc.name}' (${doc.id}): ${res.status} ${res.statusText}","messagePattern":"Failed to list folder contents for '(.+?)' \\((.+?)\\): (.+?) (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@uppy/core/src/companion-client/googlePicker.ts","lineNumber":280,"sourceCode":"  let pageToken: string | undefined\n\n  do {\n    const params = new URLSearchParams({\n      q: `'${doc.id.replace(/'/g, \"\\\\'\")}' in parents and trashed = false`,\n      fields:\n        'nextPageToken, files(id, name, mimeType, shortcutDetails(targetMimeType))',\n      includeItemsFromAllDrives: 'true',\n      supportsAllDrives: 'true',\n      pageSize: '1000',\n      ...(pageToken && { pageToken }),\n    })\n    const res = await fetch(\n      `https://www.googleapis.com/drive/v3/files?${params.toString()}`,\n      { headers, signal },\n    )\n\n    if (!res.ok) {\n      throw new Error(\n        `Failed to list folder contents for '${doc.name}' (${doc.id}): ${res.status} ${res.statusText}`,\n      )\n    }\n    const json: { nextPageToken?: string; files: PickedItemBase[] } =\n      await res.json()\n    pageToken = json.nextPageToken\n\n    for (const file of json.files) {\n      items.push(\n        ...(await handleDocObjectRecursively({ doc: file, token, signal })),\n      )\n    }\n  } while (pageToken)\n\n  return items\n}\n\nasync function showDrivePicker({","sourceCodeStart":262,"sourceCodeEnd":298,"githubUrl":"https://github.com/transloadit/uppy/blob/5d4dedd02a1ac0ae022c75c54aca76558f88e256/packages/@uppy/core/src/companion-client/googlePicker.ts#L262-L298","documentation":"Thrown while recursively expanding a picked Google Drive folder: the Drive v3 files.list call for the folder's children returned a non-OK HTTP status. The message includes the folder name/id and the HTTP status, so it identifies exactly which folder expansion failed during onPicked processing.","triggerScenarios":"After the user picks a Drive folder in the Google Picker, handleDocObjectRecursively fetches folder contents; if the Drive API responds non-OK (403 rate limit/quota, 401 token expired, 500) this error is thrown.","commonSituations":"Drive API quota exceeded; access token expired between picking and listing; insufficient Drive scopes for the folder; large folders paginated heavily hitting rate limits.","solutions":["Retry the pick/expand after a delay when status is 429/5xx","Verify the token includes drive read scope and is still valid (the plugin refreshes via googleAccounts(); ensure onAccessTokenRequired re-authorizes)","Request increased Drive API quota in Google Cloud Console","Let the user pick files directly instead of huge folders to reduce list calls"],"exampleFix":"// before\n// user picks folder -> Error: Failed to list folder contents for 'Big' (abc): 429 \n\n// after\ntry {\n  await uppy.googlePicker.showPicker()\n} catch (err) {\n  if (/Failed to list folder contents.*429/.test(err.message)) {\n    uppy.info('Drive rate limit hit — try again in a minute', 'error', 5000)\n  }\n}","handlingStrategy":"retry","validationCode":"null","typeGuard":"function isFolderListError(e: unknown): boolean {\n  return e instanceof Error && e.message.startsWith('Failed to list folder contents')\n}","tryCatchPattern":"try {\n  await picker.showPicker()\n} catch (err) {\n  const m = /: (\\d{3}) /.exec(err.message)\n  if (m && (m[1] === '429' || m[1].startsWith('5'))) await retryPicker()\n}","preventionTips":["Refresh tokens via onAccessTokenRequired for long expand operations","Discourage picking very large folders","Watch Drive API quota in Cloud Console"],"tags":["google-picker","google-drive","rate-limit","folder"],"backgroundTag":"google-api-quota-exceeded","analyzedSha":"5d4dedd02a1ac0ae022c75c54aca76558f88e256","analyzedAt":"2026-08-28T12:18:41.267Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}