zod icon indicating copy to clipboard operation
zod copied to clipboard

Weird error message when z.coerce.date() fails to coerce

Open AlonMiz opened this issue 1 month ago • 1 comments

Summary

When using z.coerce.date() with a value that cannot be coerced into a valid Date, the error message is misleading:

z.coerce.date().parse('www');
// => ZodError: Invalid input: expected date, received Date

This reads as if a Date was provided, when in fact a string was provided and the coercion produced an invalid Date. It would be helpful if the error communicated that coercion failed and/or showed the original input type/value.


Repro

import { z } from 'zod';

const schema = z.coerce.date();

schema.parse('www');          // Invalid input: expected date, received Date
schema.parse('not-a-date');   // same
schema.parse('2025-13-99');   // same (invalid calendar date)

(Using Zod v4 — reproducible in a fresh project.)


Actual behavior

  • Error message: Invalid input: expected date, received Date
  • This suggests the input was a Date, which is incorrect. The input was a string and the coercion produced new Date("www")Invalid Date.

Expected behavior

A clearer message, for example (any of these would be great):

  • Invalid date: could not coerce value "www" into a valid Date
  • Invalid input: expected a date, received string "www" (coercion failed)
  • Invalid input: expected valid Date after coercion, got Invalid Date (from "www")

Key points:

  • Indicate original input type/value (string "www").
  • Indicate that coercion happened and failed because the result is an Invalid Date.

Why this matters

  • The current message can send users on a wild goose chase, thinking they’re passing a Date incorrectly.
  • Clearer messaging speeds up debugging, especially in schemas with nested objects where the path matters.

Possible directions (implementation ideas)

  • In the coerce.date() pipeline, after coercion (new Date(value)), detect Number.isNaN(date.getTime()):

    • If Invalid Date, raise a custom issue code (e.g., "invalid_date") that includes:

      • the original input type and a safe preview of the value,
      • a hint that coercion failed.
  • Alternatively, adjust the error constructor for ZodDate to include a special branch when the input is already a Date but invalid vs. when the input was coerced from a non-Date type and resulted in Invalid Date.

  • (Nice-to-have) Add a short value preview with truncation and JSON-stringify to avoid giant messages.


Environment

  • Zod: v4.x
  • Node: v18+/v20 (reproducible)
  • TS: 5.x

Minimal code sandbox

import { z } from 'zod';
z.coerce.date().parse('www');

Thanks for the awesome library! 🙌

AlonMiz avatar Nov 02 '25 18:11 AlonMiz

Hi @AlonMiz! I'm Dosu and I’m helping the zod team.

You're right—when z.coerce.date() fails to coerce a string into a valid Date, the default error message can be misleading. This happens because Zod checks if the result is a Date instance, but doesn't distinguish between a valid and an invalid Date object, so the error message ends up saying "expected date, received Date" even if the original input was a string that failed coercion.

This behavior is recognized in the community and has been discussed in several issues and discussions. The recommended workaround is to use a custom errorMap on your schema to provide a clearer message for the "invalid_date" error code. For example:

const schema = z.coerce.date({
  errorMap: (issue, { defaultError }) =>
    issue.code === "invalid_date"
      ? { message: `Could not coerce value into a valid Date` }
      : { message: defaultError },
});

schema.parse('www'); // Throws: Could not coerce value into a valid Date

If you want to include the original input in the error, you can enable the reportInput flag during parsing and use issue.input in your error map:

schema.parse('www', { reportInput: true });
// In errorMap: issue.input will be 'www'

This approach is currently the best way to get more informative error messages for date coercion failures in Zod v4. If this answers your question, please close the issue!
References: custom errorMap workaround, related issue, error customization docs.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

dosubot[bot] avatar Nov 02 '25 18:11 dosubot[bot]