antiwork/gumroad · error · ResponseError

responseData.error_message

Error message

responseData.error_message

What it means

signupAndAddPurchaseToLibrary POSTs save_to_library_path with buyer credentials for a purchase; typia.assert narrows the reply to { success: true } | { success: false, error_message }, and the failure branch throws ResponseError carrying error_message. e.message is the server's account-creation or purchase-claim failure reason and is meant to be shown in the form.

Source

Thrown at app/javascript/data/open_in_app.ts:32

export const signupAndAddPurchaseToLibrary = async (data: SignUpAndAddPurchaseRequestData) => {
  const response = await request({
    method: "POST",
    url: Routes.save_to_library_path({ format: "json" }),
    accept: "json",
    data: {
      user: {
        email: data.email,
        purchase_id: data.purchaseId,
        buyer_signup: data.buyerSignup,
        password: data.password,
        terms_accepted: data.termsAccepted,
      },
    },
  });

  const responseData = typia.assert<SignUpResponse>(await response.json());
  if (!responseData.success) throw new ResponseError(responseData.error_message);
};

View on GitHub (pinned to afeacbd394)

Solutions

  1. On an 'already registered' style message, route the user to login instead of re-trying signup.
  2. Validate email format and the password policy client-side before POSTing.
  3. Trim the email and make sure the terms checkbox actually sets termsAccepted.
  4. Show e.message inline next to the offending field.

Example fix

// before
await signupAndAddPurchaseToLibrary({ buyerSignup: true, termsAccepted: true, purchaseId, email, password });

// after
const normalizedEmail = email.trim();
if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(normalizedEmail)) throw new Error('Enter a valid email.');
if (password.length < 8) throw new Error('Password must be at least 8 characters.');
await signupAndAddPurchaseToLibrary({ buyerSignup: true, termsAccepted: true, purchaseId, email: normalizedEmail, password });
Defensive patterns

Strategy: validation

Validate before calling

const normalizedEmail = email.trim();
if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(normalizedEmail)) throw new Error('Enter a valid email.');
if (password.length < 8) throw new Error('Password must be at least 8 characters.');
if (!termsAccepted) throw new Error('You must accept the terms to continue.');

Type guard

const isSignUpFailure = (json: unknown): json is { success: false; error_message: string } =>
  typeof json === 'object' && json !== null && (json as { success?: unknown }).success === false && typeof (json as { error_message?: unknown }).error_message === 'string';

Try / catch

try {
  await signupAndAddPurchaseToLibrary({ buyerSignup: true, termsAccepted: true, purchaseId, email, password });
} catch (e) {
  assertResponseError(e);
  if (/already (registered|has an account)/i.test(e.message)) { redirectToLogin(email); return; }
  showFieldError(e.message);
}

Prevention

When it happens

Trigger: Email already registered (an account exists — the user must sign in instead); password failing policy; terms_accepted or buyer_signup flags not actually set (the request type demands the literal true); purchase_id invalid, refunded, or already claimed by another account.

Common situations: A buyer already has a Gumroad account from an earlier purchase and tries to sign up with the same email; a pasted password with trailing whitespace; a purchase link shared with a friend who then tries to claim it.

Related errors


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