{"record":{"id":"62552294330e2b1a","repo":"antiwork/gumroad","slug":"something-went-wrong-625522","errorCode":null,"errorMessage":"Something went wrong.","messagePattern":"Something went wrong\\.","errorType":"exception","errorClass":"ResponseError","httpStatus":null,"severity":"error","filePath":"app/javascript/data/follow_embed.ts","lineNumber":10,"sourceCode":"import { request, ResponseError } from \"$app/utils/request\";\n\nexport const followFromEmbed = async (sellerId: string, email: string) => {\n  const response = await request({\n    url: Routes.follow_user_from_embed_form_path(),\n    method: \"POST\",\n    accept: \"json\",\n    data: { seller_id: sellerId, email },\n  });\n  if (!response.ok) throw new ResponseError();\n};\n","sourceCodeStart":1,"sourceCodeEnd":12,"githubUrl":"https://github.com/antiwork/gumroad/blob/afeacbd394069a1cbf0c6c50ee8e900925050370/app/javascript/data/follow_embed.ts#L1-L12","documentation":"followFromEmbed() throws at line 10 when POST Routes.follow_user_from_embed_form_path() with { seller_id, email } returns 4xx — the embeddable follow form (rendered inside iframes on external sites) failed. Beyond 422 for an invalid email and 404 for an unknown/unfollowable seller, the embed context adds auth fragility: the X-CSRF-Token header is only attached when the surrounding page set requestDefaults.headers from the csrf-token meta tag (see how custom_html_analytics.ts installs it conditionally), and third-party cookie blocking can strip the session — so 401s are disproportionately common here.","triggerScenarios":"Invalid or blank email, or autocomplete inserting 'Name <a@b.c>' instead of a bare address (422); seller deleted or deactivated while embeds still live (404); embed page lacking the csrf-token meta tag so the POST goes out without X-CSRF-Token (401); iframe cookie blocking removing the session (401).","commonSituations":"Safari/ITP and other third-party cookie blockers in embed contexts; double-submit firing a second POST that 422s; seller account deactivated after embeds were distributed.","solutions":["Validate the email client-side (bare address, single @) before submitting","Confirm the embed page includes <meta name='csrf-token'> so request() sends the header","Check DevTools for 401 vs 404/422 to separate session problems from data problems","If embeds broadly fail only in some browsers, suspect cookie blocking — offer opening the form in a top-level window"],"exampleFix":"// before\nfollowFromEmbed(sellerId, email);\n\n// after\nconst bare = email.trim().match(/^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$/);\nif (!bare) return setStatus('invalid-email');\ntry { await followFromEmbed(sellerId, email.trim()); setStatus('done'); }\ncatch (e) { assertResponseError(e); setStatus(e instanceof RateLimitError ? 'retry-later' : 'failed'); }","handlingStrategy":"validation","validationCode":"const bare = email.trim();\nif (!/^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$/.test(bare)) throw new Error('Enter a valid email address');\nif (!sellerId) throw new Error('Missing seller');","typeGuard":"const isResponseError = (e: unknown): e is ResponseError => e instanceof ResponseError;","tryCatchPattern":"try {\n  await followFromEmbed(sellerId, bare);\n  setStatus('done');\n} catch (e) {\n  assertResponseError(e);\n  if (e instanceof RateLimitError) return setStatus('retry-later');\n  setStatus('failed'); // check DevTools: 401 = embed/session, 404 = seller gone, 422 = email\n}","preventionTips":["Validate the email before POSTing; autocomplete often inserts 'Name <a@b.c>'","Ensure the embed page ships the csrf-token meta tag so requestDefaults carries X-CSRF-Token","In iframes, expect cookie blocking: detect repeated 401s and offer a top-level window fallback","Disable submit while in flight to prevent the second POST 422ing"],"tags":["gumroad","embed","iframe","follow","csrf","cookie-blocking","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"}