{"record":{"id":"3ea79275f3576511","repo":"antiwork/gumroad","slug":"something-went-wrong-3ea792","errorCode":null,"errorMessage":"Something went wrong.","messagePattern":"Something went wrong\\.","errorType":"exception","errorClass":"ResponseError","httpStatus":null,"severity":"error","filePath":"app/javascript/data/thumbnails.ts","lineNumber":27,"sourceCode":"export const createThumbnail = async (permalink: string, thumbnailPayload: ThumbnailPayload): Promise<Thumbnail> => {\n  const response = await request({\n    method: \"POST\",\n    accept: \"json\",\n    url: Routes.link_thumbnails_path(permalink),\n    data: {\n      thumbnail: { signed_blob_id: thumbnailPayload.signedBlobId },\n    },\n  });\n\n  if (response.ok) {\n    const responseData = typia.assert<{ success: true; thumbnail: Thumbnail } | { success: false; error: string }>(\n      await response.json(),\n    );\n    if (responseData.success) return responseData.thumbnail;\n    throw new ResponseError(responseData.error);\n  }\n\n  throw new ResponseError();\n};\n\nexport const deleteThumbnail = async (permalink: string, thumbnailId: string) => {\n  const response = await request({\n    method: \"DELETE\",\n    accept: \"json\",\n    url: Routes.link_thumbnail_path(permalink, thumbnailId),\n  });\n\n  if (response.ok) {\n    const responseData = typia.assert<{ success: true; thumbnail: Thumbnail } | { success: false }>(\n      await response.json(),\n    );\n    if (responseData.success) return;\n  }\n\n  throw new ResponseError();\n};","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/antiwork/gumroad/blob/afeacbd394069a1cbf0c6c50ee8e900925050370/app/javascript/data/thumbnails.ts#L9-L45","documentation":"The fallback throw in createThumbnail (app/javascript/data/thumbnails.ts:27) fires when the POST to Routes.link_thumbnails_path returns response.ok === false without reaching the success:false branch. Because request() already maps 5xx, 429, and network failures to their own errors, this is a 4xx: 401 (session expired), 403 (product not editable by this seller), or 404 (permalink does not resolve to a link). The message is the generic ResponseError default 'Something went wrong.'.","triggerScenarios":"Creating a thumbnail when the product edit page was open past session expiry (401); the permalink in the URL state is stale after the product was renamed/deleted (404); a seller without edit rights on the product posts to it (403).","commonSituations":"Editing a product in two tabs where one renamed or deleted it; long-lived edit sessions; deep-linked edit pages for products the account lost access to; tests hitting the endpoint unauthenticated.","solutions":["Reload the product edit page — a fresh page reloads permalink and session together","Verify the permalink still resolves (open the product's public/preview URL)","Confirm the acting seller has edit permission on the product","Check the POST's status code in the network tab to distinguish 401/403/404","Parse the 4xx body for an error field and surface it instead of the generic message"],"exampleFix":"// before\nthrow new ResponseError();\n\n// after — keep the server's reason when it sent one\nconst body: unknown = await response.json().catch(() => null);\nthrow new ResponseError(typia.is<{ error: string }>(body) ? body.error : \"Could not add the thumbnail.\");","handlingStrategy":"try-catch","validationCode":"const validPermalink = (p: string) => p.trim() !== \"\";\nif (!validPermalink(permalink)) throw new Error(\"Missing product permalink\");","typeGuard":"const isResponseError = (e: unknown): e is ResponseError => e instanceof ResponseError;","tryCatchPattern":"try {\n  await createThumbnail(permalink, payload);\n} catch (e) {\n  assertResponseError(e);\n  if (e.message === \"Something went wrong.\") void location.reload(); // 401 session expiry heals on reload\n  else showError(e.message);\n}","preventionTips":["Reload the edit page after long idle periods so session and permalink state stay fresh","Confirm the seller owns/controls the product before offering the thumbnail editor","Check the POST status in the network tab before debugging the uploader"],"tags":["http","fetch","thumbnails","authorization","typescript"],"backgroundTag":"http-403-forbidden","analyzedSha":"afeacbd394069a1cbf0c6c50ee8e900925050370","analyzedAt":"2026-08-21T17:58:52.159Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}