docs/solutions/logic-errors/2026-04-09-date-payload-migrations-must-canonicalize-safe-values-and-preserve-unparseable-legacy-text.md
Plate's date surface mixed three different ideas into one loose string:
That let toDateString() leak into node data, made renderers parse whatever
string happened to be there, and left no honest branch for legacy date text
that could not be normalized safely.
<date>...</date> body should parse into a real dateSplit the problem in the right order:
The new contract is:
node.date stores canonical YYYY-MM-DD<date value="YYYY-MM-DD" /><date value="YYYY-MM-DD" /> on read<date>...</date> child-text on readrawDateThe normalization helper changed the insert/render path from this:
date: date ?? new Date().toDateString()
to this shape:
const normalized = normalizeDateValue(date ?? new Date());
{
...normalized,
type: editor.getType(KEYS.date),
}
It separates the stable contract from the migration details.
Date.parse happens to accept it.These checks passed:
bun test packages/date/src/lib/transforms/insertDate.spec.tsx packages/date/src/lib/BaseDatePlugin.spec.tsx packages/date/src/lib/utils/dateValue.spec.ts packages/markdown/src/lib/dateElement.spec.ts apps/www/src/registry/ui/date-node.spec.tsx apps/www/src/registry/ui/date-node-static.spec.tsx
pnpm turbo build --filter=./packages/utils --filter=./packages/date --filter=./packages/media --filter=./packages/markdown --filter=./apps/www
pnpm turbo typecheck --filter=./packages/utils --filter=./packages/date --filter=./packages/media --filter=./packages/markdown
pnpm lint:fix
Browser verification also passed against http://127.0.0.1:3000/docs/date
through browser-use, confirming the page loaded and still surfaced the date
UI content.