A validation error that says "Invalid input" tells the user nothing about what to change. In a financial form, that friction causes abandonment — and for accessibility, WCAG 2.2 SC 3.3.1 (Error Identification) and SC 3.3.3 (Error Suggestion) require that errors both identify what is wrong and suggest a correction. "Amount must be between $0.01 and $9,999.99" passes both; "Validation failed" fails both. Generic messages also force users to guess which constraint was violated, producing support tickets that cost real money.
Info because generic error messages degrade UX and violate WCAG 2.2 SC 3.3.1 and 3.3.3 but do not directly expose data or enable exploitation.
Define explicit, constraint-naming error strings for every financial validation rule in src/lib/validationErrors.ts or inline in the Zod schema.
// src/lib/schemas.ts
export const transferSchema = z.object({
amountCents: z.number()
.int('Amount must be a whole number of cents')
.min(1, 'Minimum transaction is $0.01')
.max(99999, 'Maximum transaction is $999.99'),
routingNumber: z.string()
.regex(/^\d{9}$/, 'Routing number must be exactly 9 digits')
.refine(isValidABARoutingNumber, 'Invalid routing number — checksum failed'),
});
Return the Zod issues[0].message string directly in the API error response so the client can display it verbatim without mapping.
ID: finserv-form-validation.error-edge-cases.error-clarity
Severity: info
What to look for: List all financial form validation error messages in the codebase. For each, classify whether the message specifies the exact requirement (includes a number, format, or specific constraint) or is generic (fewer than 5 descriptive words). Quote the actual error message string found. Report: "X of Y error messages specify the exact requirement."
Pass criteria: At least 100% of financial validation error messages include the specific constraint (e.g., "Amount must be between $0.01 and $9,999.99", "Routing number must be 9 digits"). No more than 0 messages use generic text like "Invalid input" or "Validation failed".
Fail criteria: Any financial validation error message is generic or does not state the specific requirement.
Must not pass when: Error messages include the field name but not the constraint (e.g., "Invalid amount" without specifying what makes it invalid).
Skip (N/A) when: The project has no financial form validation (0 financial validation error messages found).
Detail on fail: Example: "Amount validation fails with generic 'Invalid input' instead of 'Amount must be at least $0.01'"
Cross-reference: The Error Resilience audit covers broader error messaging patterns and user-facing error recovery UX.
Remediation: Use clear, specific error messages in src/lib/schemas.ts or validation constants:
In src/lib/validationErrors.ts:
const validationErrors = {
amountTooLow: 'Minimum transaction is $0.01',
amountTooHigh: 'Maximum transaction is $9,999.99',
invalidIBAN: 'Invalid IBAN format',
invalidRoutingNumber: 'Invalid routing number',
negativeAmount: 'Amount cannot be negative',
};
if (amountCents < 1) {
return errorResponse(validationErrors.amountTooLow);
}