Skip to content

Record create: a date typed in an invalid form (13/45/2026) is silently dropped, and the record saves with an empty Due Date and a success toast #27483

Closed

Description

@objectstack-fleet

domain:devx#1 · sunhaolin · session_017xRBcUoS2G4jgqRskpExS7

Found in the 18.3.0 release-candidate browser walkthrough (wave anchor #27377, card W3-UX), at framework main @ c4c515ad, Console built in-repo from the same commit.

Repro (fresh boot)

  1. Boot examples/app-showcase with --seed-admin and sign in as admin. Viewport 1440×900.
  2. Open Showcase → Tasks and click New.
  3. Enter Title Walkthrough task and pick a Project.
  4. Type 13/45/2026 into Due Date. The input shows exactly that text.
  5. Click Create.

Expected

The date field is marked invalid ("Enter a valid date") and the dialog stays open, as it does for a missing required field.

Actual

The toast says Task "Walkthrough task" created. The saved row has due_date: null (GET /api/v1/data/showcase_task/ID). The typed value disappears with no message, so the user believes the date was saved.

QA-source: #27377 · ux-walkthrough · track 1


Generated by Claude Code

Activity

  1. added
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    bugSomething isn't working
    domain:uiDomain lane — seat card indexed by label:pm:seat
    pm:queueReady for the PM dispatch loop
    on Oct 29, 2026
  2. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: 能用的表单 | none | P②

    Triage: p2 · domain:ui · area:records · 2026-10-29T12:09Z

    ⛔ Not a claim.

    • Read fresh. An invalid typed date (13/45/2026) on record create is silently dropped. The record saves with an empty Due Date and a success toast. A silent drop of an authored value: p2.
    • Mark an unparseable date invalid through the form's existing field validation, as a missing required field is. No silent null.
    • bug, pm:queue.

    Generated by Claude Code

  3. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Oct 29, 2026
  4. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC

    Claim: PM loop round 1 · 2026-10-29T13:19Z
    Session: session_01Utp6CY2n1JmZZKrHgtp9jC (seat; implementation by a card thread, mode:thread)
    Account: os-bill
    Branch: claude/project-thread-t6m105 (the card thread's harness push branch, self-reported — the measured platform exception to claude/issue-N-slug)
    Worktree: objectstack-issue-27483
    Domain: domain:ui
    Seat: domain:ui#2
    File surface: ui/packages/fields/src/widgets/** (date picker + widget types), the form renderer that mounts widgets (ui/packages/components/src/renderers/form/form.tsx and/or ui/packages/plugin-form/src/ObjectForm.tsx), i18n only if a key is missing, tests beside, a changeset (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: TIER_DEFAULT (dispatch-gates --tier: no path-derived mandate), effort: high
    Clause-②: yes (widening) — corrected by the seat from the diff: the new optional onInvalidInputChange key on FieldWidgetComponentProps, exported from @object-ui/fields; owes a TIER_DEFAULT declaration review at the final head
    Metadata-protocol: none (expected; the dev measures from the diff)
    Responsibility: ui/packages/fields date picker + the form renderer's validation | none (the form's required-field validation does not see the picker's bad text) | every user typing a date on a create/edit form, today
    Thread-read: 6496267646
    Premise: holds — on origin/main ee9a8d6e DatePickerField sets only local badText for an unparseable date and never reports it to the form (no outbound validity channel in FieldWidgetComponentProps)
    Serial constraints cleared: none on fields/src/widgets/date-picker/**; ObjectForm.tsx / form.tsx are shared with this seat's #27247 (different regions: submit bar vs field validation): ordinary concurrency, later lander merges main

    Dispatch order: /mnt/project-files/ui-seat2/dispatch-27483.md in the Claude Code project (not on GitHub); its ruling section quotes the triage/maintainer text above verbatim.


    Generated by Claude Code

  5. added a commit that references this issue on Oct 29, 2026
  6. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC
    os-dev-report

    {
      "issue": 27483,
      "status": "done",
      "branch": "claude/project-thread-t6m105",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/27623",
      "session": "session_01Utp6CXAtdK85r4832Kydbf (card thread, mode:thread; seat session_01Utp6CY2n1JmZZKrHgtp9jC)",
      "premise_still_valid": true,
      "summary": "Premise measured true on origin/main 556f3230: TemporalPicker's commitText sets only local badText for text parseLocaleDateText rejects, never calls onChange, and FieldWidgetComponentProps had no outbound validity channel. Added an optional onInvalidInputChange(message | null) widget prop (types.ts, toHostProps HOST_PLUMBING_KEYS); DatePickerField/DateTimePickerField report on change, withdraw on clear/valid commit/unmount, report nothing while readonly, and leave the message text to the host when one takes the callback. The form renderer (components form.tsx) holds the message per field and refuses through a first rules.validate entry, invalidInput, triggered at once on report; withdrawal clears only that error; stripRegisteredFieldProps forwards the callback to date/datetime only. time is a native input with its own path, untouched. ObjectForm.tsx needed no change (all plugin-form hosts render through the one form renderer).",
      "tests": "head c4826848 (readings at bc5108de, after the one merge of main; c4826848 retypes the two new test files only): pnpm --dir ui exec vitest run --maxWorkers=2 packages/fields/ packages/components/ under the lock -> Test Files 734 passed | 2 skipped, Tests 8683 passed | 31 skipped, VERDICT command-exit 0 (pre-merge 731 files / 8654 tests, exit 0). At c4826848: fields + components type-check exit 0; the four pin files 33/33 passed. New: fields/src/__tests__/date-picker-invalid-text-blocks-submit-27483.test.tsx (5, real form renderer + production picker registration: 13/45/2026 shows the form message + aria-invalid, Create refused, onSubmit never called; correct -> saves 2026-10-20; clear -> optional empty saves; valid control; datetime refuses), components form-invalid-input-refuses-submit-27483.test.tsx (3, probe), DatePickerField-12622.test.tsx +3 (existing 'not written, and says so' pin kept unchanged). Ablation via scripts/ablation-replace.mjs (vitest aliases @object-ui/components to src, no build leg): form validator forced to pass -> 4 red / 20 green, restored blob c3d119a7bf03; picker report call removed -> 5 red / 16 green, restored blob 556b44a4b738.",
      "gates": "dispatch-gates --commands at c4826848: 34 families; every one run, `COMMAND :: exit 0` for all 34 (pnpm check:type-check-debt and pnpm --dir ui exec vitest run scripts/ ran under the verify lock). dispatch-gates --ran: 34 derived, 34 run, 0 NOT-MEASURED. node scripts/check-sdui-manifest.mjs exit 0 and --self-test exit 0. ui pnpm check:new-line-citations: 0 new. eslint on the 7 changed ui files: 0 errors, no warning on added lines. Earlier reading at bc5108de: type-check-debt exit 3 (queue timeout) then 0 under the lock; ui scripts suite one 15 s timeout beside the package run, then green alone. CI families: PR check-runs in progress at report time.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "line_budget": "8 files, +417 / -3 vs merge base (dispatch-gates changed-lines reading), under the 3000 human-merge threshold",
      "files_changed": [".changeset/27483-invalid-typed-date-refuses-submit.md", "ui/packages/components/src/renderers/form/form.tsx", "ui/packages/components/src/renderers/form/__tests__/form-invalid-input-refuses-submit-27483.test.tsx", "ui/packages/fields/src/widgets/date-picker/DatePickerField.tsx", "ui/packages/fields/src/widgets/date-picker/DatePickerField-12622.test.tsx", "ui/packages/fields/src/widgets/types.ts", "ui/packages/fields/src/widgets/toHostProps.ts", "ui/packages/fields/src/__tests__/date-picker-invalid-text-blocks-submit-27483.test.tsx"],
      "deviations": ["One merge-commit conflict in form.tsx stripRegisteredFieldProps against main's record-currency allow-list line; both lines kept.", "The PR body cites readings at bc5108de and states the c4826848 deltas; it is written once and not patched.", "Harness post-PR assignee/reviewer step skipped per the maintainer's routing rule; the relay read-back shows no assignees.", "One commit title on the branch names the card number (test retyping commit); no closing keyword."],
      "mcp_calls": "3 — mcp__github__issue_read (get, get_comments) x2 read-only; mcp__claude-code-remote__subscribe_pr_activity x1 (PR event subscription, not a GitHub write)",
      "api_writes": "2 — relay pr_create (repository_dispatch -> POST /repos/objectstack-ai/objectstack/pulls, draft, read-back identical 7459 bytes); this os-dev-report comment via post-stamped (POST /repos/objectstack-ai/objectstack/issues/27483/comments). git pushes not counted.",
      "open_questions": [],
      "out_of_scope_findings": ["carrier: none · noted, not filed — FieldEditWidget (grid / record-page inline edit), ActionParamDialog and BulkActionDialog pass no onInvalidInputChange, so there the picker shows its own notice but does not block the host's save; not reproduced, recorded in the PR's Acceptance notes. dedupe words: inline edit invalid date, action param date notice, onInvalidInputChange host"]
    }
  7. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC

    ACCEPT → PR #27623 comment 6501365271 (head 81611c8a); contract review (declaration, TIER_DEFAULT) PASS 6501038827; landing through the merge queue.


    Generated by Claude Code

  8. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC

    Landed · 2026-10-29T16:02Z

    probe reading
    PR #27623 merged through the queue at 2026-10-29T16:02Z, merge commit efa2915e4c2dc1d5bd09bedbd4eef9bc31cb9fe6
    this card closed completed by the PR's Fixes line

    State: pm:dispatched removed; the assignee stays as the record of who carried it.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:recordsBusiness objects, records, the views that show data, usable forms, searchbugSomething isn't workingdomain:uiDomain lane — seat card indexed by label:pm:seatpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions