Skip to content

Schema form reverts an edit to any field carrying a schema default #2026

Closed

Description

@cliffhall

Problem

A field whose schema declares a default can have the edit in progress reverted: text that cannot be sent reports no value, which resolves straight back to the default, and the field's draft is rewritten to it.

Reproducible today — number fields. With n: { "type": "integer", "default": 30 }, clearing the box refills it with 30. The argument cannot be emptied.

Latent — the JSON editor. The same mechanism applies to an array or object argument on the JSON fallback editor, and there it is worse (almost every edit passes through an invalid intermediate state, so the field would be uneditable). It does not reproduce through today's seeding path: collectSchemaDefaults seeds the value with the same object reference as the schema default, so the substitution returns an identical reference and the re-sync never fires. It becomes reachable the moment the field's value is a structurally-equal but distinct object — values arriving parsed from the wire or from a deep link, or a nested-object default (collectSchemaDefaults builds a fresh object for that case).

Numbers have no such protection because they are primitives: 3 → 30 is a real change.

Mechanism

Two pieces of clients/web/src/components/groups/SchemaForm/SchemaForm.tsx combine:

  1. resolveValue() substitutes the schema default whenever values[fieldName] is undefined.
  2. The two draft-holding fields re-sync their text when the parent's value diverges from what the draft parses to (SchemaNumberInput, SchemaJsonField).

A draft that cannot be sent reports undefined by design — an inspector must not report a value it cannot send. That undefined then resolves back to the default, which is a change from the previous value, so the re-sync rewrites the user's draft to the default.

It settles after one revert — from then on the value is pinned at the default and stops changing — but the keystroke is already lost.

Reproduction (number field)

Tool argument n: { "type": "integer", "default": 30 }:

  1. Open the tool. The field shows 30.
  2. Clear the box.
  3. It refills with 30.

Expected

The text being typed survives. The schema default is what the field opens with, not a value re-imposed on every unsendable draft.

Notes

Found while verifying #1853 / #1856 / #1885 and noted as out of scope in #2025. It is the same "the editor fights you" family as those three, with reversion rather than escaping as the symptom, and it is not covered by their fixes.

Sending the default is usually equivalent to omitting the argument for the tools these schemas come from, but default is a JSON Schema annotation and a server is not obliged to apply it, so the two are not guaranteed equivalent.

Edited after capturing the before/after screenshots: the original write-up claimed the array case reproduced in the app. It does not, for the reference-identity reason above; the number case does. The fix covers both, since the JSON half is one distinct object away from being live.

Activity

  1. added this to the v2.3.0 milestone on Aug 16, 2026
  2. added
    bugSomething isn't working
    v2Issues and PRs for v2
    on Aug 16, 2026
  3. cliffhall commented on Aug 16, 2026

    @cliffhall
    MemberAuthor

    Triage: Priority Medium (total 7)

    Board: #28, Status In Progress (picked up immediately).

  4. self-assigned this
    on Aug 16, 2026
  5. added a commit that references this issue on Aug 16, 2026
  6. cliffhall commented on Aug 16, 2026

    @cliffhall
    MemberAuthor

    Fixed by #2027, merged to v2/main.

    The two draft-holding fields now receive the raw value and the schema default separately and compare only against the raw one, so a default seeds what the field opens with rather than being re-imposed on every unsendable draft. The number field could not be emptied before; the JSON editor's half was latent (same-reference seeding) and is closed alongside it.

    Ships in v2.3.0.

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

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingv2Issues and PRs for v2

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions