{"record":{"id":"971c128f3e049013","repo":"antiwork/gumroad","slug":"something-went-wrong-971c12","errorCode":null,"errorMessage":"Something went wrong.","messagePattern":"Something went wrong\\.","errorType":"exception","errorClass":"ResponseError","httpStatus":null,"severity":"error","filePath":"app/javascript/data/dropbox_upload.ts","lineNumber":21,"sourceCode":"import { request, ResponseError } from \"$app/utils/request\";\n\nexport type ResponseDropboxFile = {\n  external_id: string;\n  name: string;\n  bytes: number;\n  s3_url: string | null;\n  state: \"in_progress\" | \"successfully_uploaded\" | \"cancelled\" | \"failed\" | \"deleted\";\n  dropbox_url: string;\n};\n\nexport async function uploadDropboxFile(permalink: string, file: DropboxFile) {\n  const response = await request({\n    method: \"POST\",\n    accept: \"json\",\n    url: Routes.create_dropbox_file_path(),\n    data: { ...file, link_id: permalink },\n  });\n  if (!response.ok) throw new ResponseError();\n  return typia.assert<{ dropbox_file: ResponseDropboxFile }>(await response.json());\n}\n\nexport async function cancelDropboxFileUpload(id: string) {\n  const response = await request({\n    method: \"POST\",\n    accept: \"json\",\n    url: Routes.cancel_dropbox_file_upload_path(id),\n  });\n  if (!response.ok) throw new ResponseError();\n  const json = typia.assert<{ success: false } | { dropbox_file: ResponseDropboxFile; success: true }>(\n    await response.json(),\n  );\n  if (!json.success) throw new ResponseError();\n  return json.dropbox_file;\n}\n\nexport async function fetchDropboxFiles(permalink: string) {","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/antiwork/gumroad/blob/afeacbd394069a1cbf0c6c50ee8e900925050370/app/javascript/data/dropbox_upload.ts#L3-L39","documentation":"uploadDropboxFile() throws at line 21 when POST Routes.create_dropbox_file_path() with { ...file, link_id: permalink } returns 4xx — registering a Dropbox-hosted file on a product failed. The spread of the client-shaped DropboxFile forwards raw input to the server, where validation decides: 422 for an invalid dropbox_url/oversized file, 404 for an unknown or unpublished link_id, 403 when the caller does not own the link. A separate typia.assert on the success body at line 22 is a different failure mode.","triggerScenarios":"dropbox_url not a valid Dropbox share link (422); file bytes/name over the endpoint's limits (422); link_id for a deleted or unpublished product (404); session not the link owner (403); CSRF (401).","commonSituations":"Users pasting Google Drive or plain URLs into the Dropbox field; product deleted while the uploader panel was open; deploys changing upload limits so previously-fine files now 422.","solutions":["Validate the URL is an https Dropbox link client-side before POSTing","Refetch the product/link to confirm it still exists and is published","Read the status in DevTools: 422 = payload validation, 404 = bad link_id, 403 = ownership","If the request succeeds but parsing throws, that is the typia line 22 branch (response shape drift), not this one"],"exampleFix":"// before\nuploadDropboxFile(permalink, file);\n\n// after\nif (!file.dropbox_url.startsWith('https://www.dropbox.com/')) {\n  return toast('Paste a Dropbox share link (https://www.dropbox.com/...)');\n}\nawait uploadDropboxFile(permalink, file);","handlingStrategy":"validation","validationCode":"if (!/^https:\\/\\/www\\.dropbox\\.com\\//.test(file.dropbox_url)) {\n  throw new Error('Paste a Dropbox share link (https://www.dropbox.com/...)');\n}\nif (!permalink) throw new Error('Missing product permalink');","typeGuard":"const isResponseError = (e: unknown): e is ResponseError => e instanceof ResponseError;","tryCatchPattern":"try {\n  const { dropbox_file } = await uploadDropboxFile(permalink, file);\n  addFile(dropbox_file);\n} catch (e) {\n  assertResponseError(e);\n  if (e instanceof RateLimitError) return showRetryLater(e.retryAfter);\n  toast('Could not add the file. Check the Dropbox link and that the product still exists.');\n}","preventionTips":["Validate the dropbox_url prefix client-side; most 422s are non-Dropbox or scheme-less links","Confirm the product (permalink) still exists and is published before opening the uploader","A status-ok response that throws is the typia line 22 branch — schema drift, not upload failure","Send only known fields rather than spreading arbitrary form state into data"],"tags":["gumroad","dropbox","file-upload","product-files","fetch","http-4xx","typescript"],"backgroundTag":"http-4xx-client-error","analyzedSha":"afeacbd394069a1cbf0c6c50ee8e900925050370","analyzedAt":"2026-08-21T17:58:52.159Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}