createMessageBuilder

The createMessageBuilder function is the core string-formatting engine of zod-validation-error. It takes raw Zod issues and combines them into a polished, final string.

Philosophy: ErrorMap vs MessageBuilder

It is important to understand the pipeline:

  1. Error Map: Formats individual issues (e.g., translates too_small into "Number must be greater than 0").
  2. Message Builder: Takes that array of formatted strings, adds paths (e.g., at "user.age"), joins them together with separators (e.g., ;), and prepends a prefix.

Signature

type MessageBuilder = (issues: NonEmptyArray<ZodIssue>) => string;

function createMessageBuilder(
  partialOptions?: Partial<MessageBuilderOptions>
): MessageBuilder

Configuration Options (MessageBuilderOptions)

You can pass these options to createMessageBuilder directly, or you can pass them in the options argument of fromError and fromZodError (which creates a Message Builder under the hood).

Option Type Default Description
maxIssuesInMessage number 99 The maximum number of issues to display before truncating.
issueSeparator string "; " The string used to join multiple distinct issues.
unionSeparator string " or " The string used to join issues arising from zod.union failures.
prefix string &#124; null "Validation error" The prefix appended to the very front of the error message. Pass null to disable completely.
prefixSeparator string ": " The string joining the prefix to the first issue (ignored if prefix is null).
includePath boolean true Whether to include the property path (e.g., at "user.name") in the message.
forceTitleCase boolean true Whether to capitalize the first letter of every individual issue message.

Examples

Standard Customization via fromError

Usually, you don't need to call createMessageBuilder directly. You pass its options to fromError:

import { fromError } from 'zod-validation-error';

const err = fromError(zodError, {
  prefix: 'Form Submission Failed',
  issueSeparator: '\n - ',
  includePath: false, // Don't show technical paths to the user
});

// Output:
// Form Submission Failed: 
//  - Invalid email address
//  - String must contain at least 5 character(s)

Creating a Fully Custom Message Builder

If the configuration options aren't enough, you can bypass createMessageBuilder entirely and write your own MessageBuilder function from scratch.

This is useful if you want to implement syntax highlighting (e.g., via chalk) for CLI tools.

import { z as zod } from 'zod';
import { type MessageBuilder, fromError } from 'zod-validation-error';
import chalk from 'chalk';

// Write a completely custom builder
const myMessageBuilder: MessageBuilder = (issues) => {
  return issues
    .map((issue) => {
      // Colorize the path in yellow, and the message in red
      const path = issue.path.join('.');
      return `${chalk.yellow(path)}: ${chalk.red(issue.message)}`;
    })
    .join('\n');
};

const schema = zod.object({ email: zod.email() });
const result = schema.safeParse({ email: 'bad' });

if (!result.success) {
  const validationError = fromError(result.error, {
    // Inject your custom builder
    messageBuilder: myMessageBuilder,
  });
  console.log(validationError.toString());
}