antiwork/gumroad · error · ResponseError
Something went wrong.
Error message
Something went wrong.
What it means
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.
Source
Thrown at app/javascript/data/follow_embed.ts:10
import { request, ResponseError } from "$app/utils/request";
export const followFromEmbed = async (sellerId: string, email: string) => {
const response = await request({
url: Routes.follow_user_from_embed_form_path(),
method: "POST",
accept: "json",
data: { seller_id: sellerId, email },
});
if (!response.ok) throw new ResponseError();
};
View on GitHub (pinned to afeacbd394)
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
Example fix
// before
followFromEmbed(sellerId, email);
// after
const bare = email.trim().match(/^[^@\s]+@[^@\s]+\.[^@\s]+$/);
if (!bare) return setStatus('invalid-email');
try { await followFromEmbed(sellerId, email.trim()); setStatus('done'); }
catch (e) { assertResponseError(e); setStatus(e instanceof RateLimitError ? 'retry-later' : 'failed'); } Defensive patterns
Strategy: validation
Validate before calling
const bare = email.trim();
if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(bare)) throw new Error('Enter a valid email address');
if (!sellerId) throw new Error('Missing seller'); Type guard
const isResponseError = (e: unknown): e is ResponseError => e instanceof ResponseError;
Try / catch
try {
await followFromEmbed(sellerId, bare);
setStatus('done');
} catch (e) {
assertResponseError(e);
if (e instanceof RateLimitError) return setStatus('retry-later');
setStatus('failed'); // check DevTools: 401 = embed/session, 404 = seller gone, 422 = email
} Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Something went wrong.
- Something went wrong.
- ${response.message}
- Something went wrong.
- Something went wrong.
AI-assisted analysis of antiwork/gumroad@afeacbd394 (2026-08-21).
Data as JSON: /api/errors/62552294330e2b1a.
Report an issue: GitHub.