antiwork/gumroad · error · ResponseError
We couldn't sign you in with that passkey. Please try again
Error message
We couldn't sign you in with that passkey. Please try again or use your password.
What it means
Fallback shown when the first step of passkey sign-in on /login fails: POSTing to Routes.login_passkey_options_path to fetch WebAuthn authentication options. It throws ResponseError with the server's error_message when !optionsResponse.ok, success is false, or options is missing — or when typia.assert rejects a malformed body. The catch deliberately swallows AbortError and browser DOMException NotAllowedError/AbortError, so user cancellations of the native passkey sheet never surface this message; only genuine fetch/option failures set the visible passkey error.
Source
Thrown at app/javascript/pages/Logins/New.tsx:106
signal?: AbortSignal;
surfaceErrors: boolean;
}) => {
try {
let options = embeddedOptions;
if (!options) {
const optionsResponse = await request({
url: Routes.login_passkey_options_path(),
method: "POST",
accept: "json",
abortSignal: signal,
});
const optionsResult = typia.assert<{
success: boolean;
options?: PasskeyAuthenticationOptions;
error_message?: string;
}>(await optionsResponse.json());
if (!optionsResponse.ok || !optionsResult.success || !optionsResult.options) {
throw new ResponseError(optionsResult.error_message ?? PASSKEY_ERROR);
}
options = optionsResult.options;
}
const credential = await getPasskey(options, { mediation, signal });
setPasskeyLoading(true);
const loginResponse = await request({
url: Routes.login_passkey_path(),
method: "POST",
accept: "json",
data: { credential, next },
abortSignal: signal,
});
const loginResult = typia.assert<{ success: boolean; redirect_location?: string; error_message?: string }>(
await loginResponse.json(),
);View on GitHub (pinned to afeacbd394)
Solutions
- Retry the passkey button — transient option-fetch failures are common.
- If it persists, use password sign-in (the message's own fallback).
- Devtools: check the passkey_options POST status and body — a server error_message would have been shown verbatim, so this fallback means the body had none.
- Maintainers: keep the { success, options, error_message } shape stable; typia violations surface as this same generic fallback.
Defensive patterns
Strategy: try-catch
Type guard
const isOptionsFetchFailure = (
response: Response,
result: { success?: boolean; options?: PasskeyAuthenticationOptions },
): boolean => !response.ok || result.success !== true || result.options == null; Try / catch
try {
const optionsResponse = await request({ url: Routes.login_passkey_options_path(), method: "POST", accept: "json", abortSignal: signal });
const optionsResult = typia.assert<{ success: boolean; options?: PasskeyAuthenticationOptions; error_message?: string }>(await optionsResponse.json());
if (!optionsResponse.ok || !optionsResult.success || !optionsResult.options) {
throw new ResponseError(optionsResult.error_message ?? PASSKEY_ERROR);
}
} catch (e) {
if (!signal?.aborted) setLoading(false);
if (e instanceof AbortError) return;
if (e instanceof DOMException && (e.name === "NotAllowedError" || e.name === "AbortError")) return; // user dismissed the native sheet
if (surfaceErrors) setPasskeyError(e instanceof ResponseError ? e.message : PASSKEY_ERROR);
} Prevention
- Always pass an AbortSignal so cancellations don't surface as user-visible errors.
- Swallow NotAllowedError — the user closing the native prompt is not a failure.
- Keep the options endpoint cheap and unthrottled so first-hit reliability is high.
When it happens
Trigger: POST /login/passkey_options returns 4xx/5xx (rate limit, CSRF/session problem, server error), success:false (no credentials match), options omitted, or the response body drifts from the asserted { success, options, error_message } shape.
Common situations: Conditional-UI/usernameless autofall kicking off before cookies are ready, Rails route or serialization changes breaking the options contract, aggressive rate limiting on repeated attempts, or users with no registered passkeys pressing the passkey button.
Related errors
- Sorry, something went wrong. Please try again.
- Could not add this passkey. Please try again.
- missing_challenge
- deleted_user
- unknown_credential
AI-assisted analysis of antiwork/gumroad@afeacbd394 (2026-08-21).
Data as JSON: /api/errors/cbf4749cce8b3d85.
Report an issue: GitHub.