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

  1. Validate the email client-side (bare address, single @) before submitting
  2. Confirm the embed page includes <meta name='csrf-token'> so request() sends the header
  3. Check DevTools for 401 vs 404/422 to separate session problems from data problems
  4. 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

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


AI-assisted analysis of antiwork/gumroad@afeacbd394 (2026-08-21). Data as JSON: /api/errors/62552294330e2b1a. Report an issue: GitHub.