Skip to content

Improve Default Validation Messages for Forms and APIs #1453

@heiwen

Description

@heiwen

Summary

Valibot's current issue objects contain enough structural detail for forms, APIs, and agentic tooling, but the default message strings are still mostly validator-facing rather than user-facing.

In practice, this means application code often has to override or remap the default message for nearly every field before showing validation feedback in a UI. That creates repetitive boilerplate, increases maintenance cost, and reduces the value of having strong built-in defaults in the first place.

This ticket proposes improving the default message generation only, while keeping the existing issue/output structure unchanged.

Problem

Today, Valibot messages are technically correct, but many of them are not ideal as defaults for:

  • form field errors shown directly to end users
  • API validation responses consumed by frontend clients
  • agent/tooling workflows that benefit from cleaner semantic phrasing

Examples of current messages:

  • Invalid key: Expected "age" but received undefined
  • Invalid type: Expected number but received "17"
  • Invalid length: Expected >=8 but received 3
  • Invalid email: Received ""

These messages expose implementation details and validator terminology:

  • expected / received
  • quoted raw values
  • undefined
  • Invalid key
  • constraint syntax such as >=8

That wording is useful for debugging, but weak as a default for user-facing validation.

Goal

Improve the default message values so they are more friendly for forms and APIs, without changing:

  • issue object shape
  • path structure
  • kind
  • type
  • expected
  • received
  • nested issues

This is a message-quality improvement, not a schema/result-shape redesign.

Non-Goals

  • Do not change the current issue structure.
  • Do not remove existing metadata such as expected, received, input, or path.
  • Do not require a new formatter API for the initial improvement.
  • Do not reduce debugging detail outside of the message field.

Why This Matters

Valibot already has strong primitives:

  • detailed issue metadata
  • structured paths
  • flatten(...)
  • summarize(...)

The main gap is the wording of default messages. Improving only message would make Valibot much more usable out of the box for:

  • direct form field rendering
  • API validation responses
  • generic client-side error mappers

Proposed Direction

Keep the same issue objects, but revise the default message generation to be more semantic and less diagnostic.

Examples:

Current message Better default message
Invalid key: Expected "age" but received undefined Age is required
Invalid key: Expected "website" but received undefined Website is required
Invalid type: Expected number but received "17" Age must be a number
Invalid type: Expected ("admin" | "member") but received "boss" Role must be one of: admin, member
Invalid length: Expected >=8 but received 3 Password must be at least 8 characters
Invalid email: Received "not-an-email" Enter a valid email address
Invalid URL: Received "wat" Enter a valid URL

Suggested Message Rules

Required / missing keys

Current missing-key messages are the weakest part of the UX.

Instead of:

  • Invalid key: Expected "age" but received undefined

Prefer:

  • Age is required

Invalid type

Instead of:

  • Invalid type: Expected number but received "17"

Prefer:

  • Age must be a number

Invalid format

Instead of:

  • Invalid email: Received "foo"
  • Invalid URL: Received "wat"

Prefer:

  • Enter a valid email address
  • Enter a valid URL

Length / size constraints

Instead of:

  • Invalid length: Expected >=8 but received 3

Prefer:

  • Password must be at least 8 characters

Desired Outcome

After this change, consumers who directly surface issue.message should get defaults that are:

  • safer to show to users
  • less diagnostic/noisy
  • more consistent across validators
  • easier to use in forms without custom per-field copy

Advanced consumers would still retain full access to:

  • type
  • expected
  • received
  • path
  • nested issue metadata

Acceptance Criteria

  • Default Valibot messages are more user-facing for common validation failures.
  • Missing required object keys no longer default to Invalid key: Expected ... received undefined.
  • Common formats like email and URL use friendlier wording.
  • Type mismatch messages avoid overly diagnostic phrasing by default.
  • Issue/result object shape remains unchanged.
  • Existing metadata fields remain available for advanced formatting/debugging.

Optional Follow-Up

Once the default messages are improved, Valibot could optionally add presets later such as:

  • debug
  • form
  • api
  • agent

But that is not required for this ticket. The immediate ask is only to improve the default message strings while preserving the existing structure.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestnext versionSomething to look at for our next major release

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions