Errors
Stable error codes, field issues, and helpers for mapping them in the UI.
Failed requests return JSON with a stable code, an English message, and optional issues.
Standard Error Response Schema
type ErrorResponseBody = {
/** Human-readable explanation of the error */
message: string;
/** Stable machine-readable error code */
code?: string;
/** Optional parameters for message interpolation */
params?: Record<string, string | number>;
/** Field-level validation issues (present on VALIDATION_ERROR) */
issues?: Array<{
field: string;
message: string;
code?: string;
params?: Record<string, string | number>;
}>;
};Core Error Codes (FORM_ERROR_CODES)
| Error Code | HTTP Status | Trigger Condition |
|---|---|---|
NOT_FOUND | 404 | Requested URL route does not match any registered endpoint. |
UNKNOWN_FORM | 404 | Form ID or slug could not be found in code catalogs or database. |
UNKNOWN_RESPONSE | 404 | Response ID does not exist in the database. |
UNAUTHORIZED | 401 | Thrown by guard when the user is unauthenticated. |
FORBIDDEN | 403 | Thrown by guard when the user lacks permissions or ownership. |
STALE_UPDATE | 409 | updatedAt CAS token mismatch (concurrent write collision). |
FORM_INACTIVE | 409 | startResponse called on a form with status "draft" or "archived". |
RESPONSE_NOT_DRAFT | 409 | saveDraft or submitResponse attempted on a locked response. |
RESPONSE_NOT_LOCKED | 409 | reopenResponse attempted on an active draft response. |
CODE_AUTHORED_FORM | 409 | Overwrite (saveForm) or delete (deleteForm) attempted on a code-authored form. |
FORM_HAS_RESPONSES | 409 | deleteForm attempted on a form that already has recorded responses. |
SLUG_TAKEN | 409 | Form slug collides with an existing form. |
VALIDATION_ERROR | 400 | Payload or answer validation failure (inspect issues[]). |
UNKNOWN_FIELD_TYPE | 400 | Form references a field type not registered in fieldTypes. |
RESUME_REQUIRES_RESPONDENT | 400 | startResponse({ resume: true }) called without a respondentId. |
INTERNAL_ERROR | 500 | Unhandled server exception. |
Field Issue Codes (FIELD_ISSUE_CODES)
When a 400 VALIDATION_ERROR occurs during submission, the issues[] array contains field-specific issue codes:
| Issue Code | Description | Parameters |
|---|---|---|
REQUIRED | Visible required field was left empty on submit. | — |
UNKNOWN_FIELD | Answer key does not exist in the form snapshot. | — |
UNKNOWN_FIELD_TYPE | Field type has no registered validator. | { type } |
INVALID | Custom validator rejected the answer. | — |
EXPECTED_STRING | Answer must be a string. | — |
EXPECTED_NUMBER | Answer must be a finite number. | — |
EXPECTED_INTEGER | Answer must be an integer. | — |
EXPECTED_BOOLEAN | Answer must be a boolean (true or false). | — |
EXPECTED_STRING_ARRAY | Answer must be an array of strings. | — |
EXPECTED_EMAIL | Answer must be a valid email address. | — |
EXPECTED_DATE | Answer must be an ISO calendar date (YYYY-MM-DD). | — |
TOO_SHORT | Text length is below minLength. | { min } |
TOO_LONG | Text length exceeds maxLength. | { max } |
TOO_SMALL | Numeric value is below min. | { min } |
TOO_LARGE | Numeric value exceeds max. | { max } |
INVALID_FORMAT | Text does not match the configured pattern regex. | — |
INVALID_OPTION | Selected value is not in the allowed options list. | — |
DUPLICATE_OPTION | multiSelect array contains duplicate values. | — |
Client Error Helpers
@dimah-form/react provides helpers to map error codes to user-friendly or localized messages:
import {
fieldIssueMap,
formErrorMessage,
issuesByField,
} from "@dimah-form/react";
// Convert APIError issues array into a field-id-to-message map
const issues = fieldIssueMap(apiError);
// { fullName: "Full Name is required", email: "Invalid email" }
// Extract formatted top-level error message
const message = formErrorMessage(error);Declaring Custom Error Codes with defineErrorCodes
When authoring plugins or custom field validators, use defineErrorCodes() to declare type-safe custom error catalogs:
import { defineErrorCodes } from "@dimah-form/server";
export const CUSTOM_ERROR_CODES = defineErrorCodes({
PAYMENT_REQUIRED: "Payment verification failed",
SUBSCRIPTION_EXPIRED: "Account subscription is inactive",
});