Skip to content

Console FormPage submits a cleared server-owned field as '' — no omitServerResolvedDefaults equivalent, so the declared runtime default is still suppressed on that path #5883

Description

@claude

Found while implementing #5727 (guarding readPrefill's seeding with isRuntimeDefault). Not fixed in that PR — that card's fence was the seeding half, and this is the submit half: a different call site, a different predicate, and its own decision about what "empty" means.

Measured on origin/main1939c9610.

Mechanism

After #5727 a create form on the console's two form routes correctly opens a runtime-default control EMPTY and leaves the key out of values. But handleSubmit submits values wholesale:

constresult=mode==='public'
? awaitsubmitPublic(identifier,values)
: awaitsubmitInternal(loaded.object,values,editingId);

A rendered control that the user focuses and then clears writes back through onChange={(e) => onChange(e.target.value)} (FieldInput, the text/email/url/date/time/textarea arms), so values gains the key with ''. ObjectQL.applyFieldDefaults resolves a declared default only for a field that arrives absent or null — a blank string is neither, so submitting one stores '' and silently defeats the declaration. That is the same suppression #5727 closed, reached by the other door.

The sibling chain already has the answer and names it as the other half of the same fix: @object-ui/plugin-form's omitServerResolvedDefaults (packages/plugin-form/src/schemaDefaults.ts) drops exactly the keys whose declared default isRuntimeDefault and whose submitted value isMissingForRequired. Its docblock states the pairing outright — "excusing a server-owned field from required is only half an answer if the form then submits the key anyway". apps/console/src/components/FormPage.tsx calls no equivalent: omitServerResolvedDefaults returns zero hits in that file.

Why this is not a duplicate

Honestly bounded

Not browser-verified. Static evidence: the handleSubmit call site, the onChange write, the absent omitServerResolvedDefaults call, and the sibling module's own statement that the two halves belong together. Reachability requires the user to touch and clear the control, which narrows it relative to #5727 (that one fired on every open). Note also that the console builds its payload from values rather than from an object schema keyed by field name, so whether the sibling's signature (data, objectSchema) fits this call site as-is, or the fence wants the RenderableField rows it already holds, is a call for triage rather than for this note.

Related: #5727, #4047, #4068, #4069, #4085.


Generated by Claude Code

Metadata

Metadata

Assignees

Labels

domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpm:dispatched

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions