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
- On an 'already registered' style message, route the user to login instead of re-trying signup.
- Validate email format and the password policy client-side before POSTing.
- Trim the email and make sure the terms checkbox actually sets termsAccepted.
- 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
- Validate email format and password policy client-side before the POST.
- Route 'account exists' failures to the login flow instead of re-trying signup.
- Trim email input; require the terms checkbox before enabling submit.
- Never swallow error_message — it is the only actionable text the endpoint returns.
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
- responseData.error_message
- ${data.error}
- We couldn't sign you in with that passkey. Please try again
- ${responseData.error}
- Something went wrong.
AI-assisted analysis of antiwork/gumroad@afeacbd394 (2026-08-21).
Data as JSON: /api/errors/5277d8a543f2a444.
Report an issue: GitHub.