k.issue
Emit a validation issue with a machine-readable code, checked against the codes your config declares.
Emit a single Zod validation issue carrying a custom machine-readable code. The code is surfaced verbatim in the errors[].code field of Kizuna's ValidationErrorSchema.
The code is checked against the validation.issueCodes you declared on defineConfig, so a typo is a compile error.
Zod's types restrict ctx.addIssue() to its built-in issue union, so a custom code needs a cast at every call site. k.issue holds that cast.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | z.core.$RefinementCtx<Input> | The refinement context from .superRefine(). |
issue.code | Codes | BuiltinIssueCode | One of the validation.issueCodes declared on defineConfig, or a built-in Zod code. Surfaced in errors[].code. |
issue.message | string | Human-readable description of the failure. |
issue.input | Input | The value that failed validation. |
Example
A request whose body fails this refinement returns 400 with the custom code in the response:
Typed codes on the client
By default errors[].code is typed as ValidationIssueCode, so the built-in Zod codes are suggested in autocomplete and any custom string is accepted, but your invalid_phone_number is not suggested (it lives only inside the refinement callback, where TypeScript can't see it).
To make the client suggest your custom codes, declare them under validation.issueCodes on defineConfig and regenerate the fetch client:
Now errors[].code on a 400 response is widened to ValidationIssueCode | 'invalid_phone_number', so invalid_phone_number shows up in autocomplete when you read or compare it:
Each API has its own config, so codes stay scoped to it.
See isValidationError for how clients consume these codes.