Description
A collection field can declare validation constraints (maxLength, min, minItems, pattern). These are enforced server-side by the generated Zod schema, but nothing in the admin surfaces them to the person typing. The editor's first and only signal is a failed save.
Since #1838 that failure message is at least specific — the toast reads excerpt: Too big: expected string to have <=160 characters rather than the old generic "Invalid request data", which is a real improvement. But it arrives after the fact, names the field by slug rather than by its label, uses validator-internal phrasing, and — the substantive part of this report — autosave keeps retrying a request that can never succeed.
In one editing session on 0.32.0 we recorded 443 failed PUTs to the same entry over 23.4 minutes, a median of 3.0 seconds apart (~19/min), every one a 400 with the identical body. Each produced its own toast. The author had added a few words to a summary field capped at 160 characters; nothing in the UI had indicated a cap existed.
Steps to reproduce
- Declare a text field with
validation: { maxLength: 160 } in a collection.
- Open an entry in the admin and type past 160 characters in that field.
- Observe: no counter, no
maxlength, no help text — nothing marks the limit while typing.
- Wait. Autosave fires, fails 400, and toasts
excerpt: Too big: expected string to have <=160 characters.
- Leave the tab open. Autosave retries every ~3 seconds indefinitely, toasting each time, with no back-off and no terminal state.
Observed
- The constraint is unknowable from the UI until it is violated.
- The message identifies the field by slug (
excerpt), not by the label the editor actually sees ("Summary").
- The message is the raw validator string ("Too big: expected string to have <=160 characters") rather than a sentence aimed at an author.
- Autosave treats a permanent 400 as retryable. 443 attempts, 23.4 minutes, no escalation, no stop, no back-off.
Expected
- Constraints declared in the schema are visible while editing — at minimum a character counter or
maxlength on length-limited fields, and help text derived from validation rather than hand-written into the label.
- Validation errors name the field by its label.
- Autosave treats a 4xx other than 429 as terminal: stop retrying, keep the buffer dirty, surface the problem once, and retry only when the content changes again.
Why this matters beyond one field
We audited our own schema after hitting this: 16 of 17 declared constraints never reach the editor's screen. The single exception is the field in this report, and only because a developer had previously hand-typed "max 160 chars" into its label — after an earlier incident. That workaround is unchecked: change maxLength to 200 and the label still says 160.
The options constraints are effectively surfaced, because a select renders the allowed set. Everything expressed as a number or a pattern — maxLength, min, minItems, pattern — is invisible. A non-technical author cannot discover any of it except by tripping it.
Related
Environment
- emdash 0.32.0
- Astro node adapter, PostgreSQL 18 adapter
- Reproduced against a production-shaped content set; server responses captured from load-balancer access logs, so the retry counts above are measured rather than estimated.
Notes on possible fixes
Roughly in increasing order of effort:
- Stop the retry storm. Classify non-429 4xx as terminal in the autosave client. This alone removes 442 of the 443 requests and the toast pile.
- Use the label in the message. The field descriptor already carries both slug and label.
- Render the constraint. Pass
validation through to the field renderer: maxlength plus a live counter for length-limited strings, min/max on numerics, and generated help text. This is the fix that would have prevented the situation entirely.
Happy to open a PR for (1) and (2) if that would be useful — they look self-contained, and (1) is the one that turns a papercut into a non-event.
Description
A collection field can declare
validationconstraints (maxLength,min,minItems,pattern). These are enforced server-side by the generated Zod schema, but nothing in the admin surfaces them to the person typing. The editor's first and only signal is a failed save.Since #1838 that failure message is at least specific — the toast reads
excerpt: Too big: expected string to have <=160 charactersrather than the old generic "Invalid request data", which is a real improvement. But it arrives after the fact, names the field by slug rather than by its label, uses validator-internal phrasing, and — the substantive part of this report — autosave keeps retrying a request that can never succeed.In one editing session on 0.32.0 we recorded 443 failed
PUTs to the same entry over 23.4 minutes, a median of 3.0 seconds apart (~19/min), every one a 400 with the identical body. Each produced its own toast. The author had added a few words to a summary field capped at 160 characters; nothing in the UI had indicated a cap existed.Steps to reproduce
validation: { maxLength: 160 }in a collection.maxlength, no help text — nothing marks the limit while typing.excerpt: Too big: expected string to have <=160 characters.Observed
excerpt), not by the label the editor actually sees ("Summary").Expected
maxlengthon length-limited fields, and help text derived fromvalidationrather than hand-written into the label.Why this matters beyond one field
We audited our own schema after hitting this: 16 of 17 declared constraints never reach the editor's screen. The single exception is the field in this report, and only because a developer had previously hand-typed "max 160 chars" into its label — after an earlier incident. That workaround is unchecked: change
maxLengthto 200 and the label still says 160.The
optionsconstraints are effectively surfaced, because a select renders the allowed set. Everything expressed as a number or a pattern —maxLength,min,minItems,pattern— is invisible. A non-technical author cannot discover any of it except by tripping it.Related
min/maxand required subfields not enforced by runtime content validation. Same family: constraints declared in the schema that do not take effect where an author would meet them.Environment
Notes on possible fixes
Roughly in increasing order of effort:
validationthrough to the field renderer:maxlengthplus a live counter for length-limited strings,min/maxon numerics, and generated help text. This is the fix that would have prevented the situation entirely.Happy to open a PR for (1) and (2) if that would be useful — they look self-contained, and (1) is the one that turns a papercut into a non-event.