antiwork/gumroad · error · ResponseError
typia.assert<{ message: string }>(await response.json()).mes
Error message
typia.assert<{ message: string }>(await response.json()).message What it means
previewInstallment POSTs internal_installment_preview_email_path and on non-ok asserts the body is { message: string }, throwing ResponseError with that message. Same dual failure as its sibling at line 176: a well-formed { message } body yields the intended ResponseError, but any other failure body (HTML page, empty body, or a body keyed error) makes typia.assert throw a TypeError from inside the error path.
Source
Thrown at app/javascript/data/installments.ts:187
const response = await request({
method: "POST",
accept: "json",
url: Routes.internal_installment_non_opener_resend_path(externalId),
});
const json: unknown = await response.json();
if (!response.ok) throw new ResponseError(typia.assert<{ error: string }>(json).error);
return typia.assert<{ success: boolean }>(json);
}
export async function previewInstallment(externalId: string) {
const response = await request({
method: "POST",
accept: "json",
url: Routes.internal_installment_preview_email_path(externalId),
});
if (!response.ok) throw new ResponseError(typia.assert<{ message: string }>(await response.json()).message);
}
View on GitHub (pinned to afeacbd394)
Solutions
- Inspect the failing response body in the Network tab and check the key is message, not error.
- Standardize the installment endpoints on one error-body shape, or extract defensively with a type guard instead of typia.assert.
- Fix the server render path so JSON-only endpoints never fall through to an HTML error page.
- Show e.message (ResponseError) and log TypeError separately — they mean different defects.
Example fix
// before
if (!response.ok) throw new ResponseError(typia.assert<{ message: string }>(await response.json()).message);
// after
if (!response.ok) {
const json: unknown = await response.json();
const message =
typeof json === 'object' && json !== null && 'message' in json && typeof (json as { message: unknown }).message === 'string'
? (json as { message: string }).message
: 'Could not preview this installment.';
throw new ResponseError(message);
} Defensive patterns
Strategy: try-catch
Type guard
const hasMessageBody = (json: unknown): json is { message: string } =>
typeof json === 'object' && json !== null && 'message' in json && typeof (json as { message: unknown }).message === 'string'; Try / catch
try {
await previewInstallment(externalId);
} catch (e) {
if (!(e instanceof ResponseError)) {
console.error('Unexpected error body', e); // typia TypeError — body wasn't { message: string }
showError('Could not preview this installment.');
} else {
showError(e.message);
}
} Prevention
- Check which key (message vs error) this endpoint's failure body actually uses before asserting.
- Keep a shared defensive extractor for error bodies across the installments module.
- Ensure server exception handling renders JSON, never HTML, on json endpoints.
When it happens
Trigger: A 4xx with a JSON { message } body → ResponseError carrying the server text (e.g., 'Installment has no email body'). A 4xx whose body is keyed error — which the sibling resend endpoint uses — or is HTML/empty → typia TypeError on $input.message.
Common situations: Two endpoints in the same file expecting different error-body keys; an exception-rendering path that returns HTML while handlers assume JSON; previewing an installment whose email template fails to render server-side.
Related errors
- typia.assert<{ error: string }>(json).error
- ${data.error}
- ${responseData.error}
- Something went wrong.
- responseData.error_message
AI-assisted analysis of antiwork/gumroad@afeacbd394 (2026-08-21).
Data as JSON: /api/errors/888e27364749d309.
Report an issue: GitHub.