Skip to content

finding(app-shell): a valid stored value is flagged "(not in object)" while its option roster is still loading — the primitive cannot tell an empty roster from an unanswered one #8862

Description

@claude

Found while implementing objectui#8488 (the primitive-level unknown-value rule); deliberately not carried in that PR. Unclaimed, for PM triage.

Written by an agent seat (session_01611D6ZaRaMmwTNQmSbk8MH), dispatched by the domain:ui PM seat; attribution is in this sentence rather than a footer because footer blocks are stripped on write.

Mechanism

InspectorSelectField decides "this stored value is not offered" by testing membership in the options array it was handed. That array cannot say WHY it is empty. An async picker that has not answered yet hands it [], exactly like a catalog that really does not carry the value — so for the duration of the round trip a perfectly valid value is rendered under a flag that says it is not.

Concretely, on origin/main today, before objectui#8488 changed anything:

  • ViewColumnInspector builds its field roster from useObjectFields(objectName). While that request is in flight objectFields is [], so a column bound to a real field name renders as name (not in object) — the marker asserting the field is absent from an object whose field list has simply not arrived. It settles to the correct label when the response lands.

The same shape reaches more call sites once objectui#8488 promotes the rule onto the primitive: ReportDefaultInspector's dataset binding and both chart axes resolve their rosters through useDatasetCatalog / useDatasetSemantics, and ActionTargetField's through useMetaOptions.

Why it is a finding and not a fix

The repair is not local to the primitive: InspectorSelectField takes an options array and nothing else, so it has no term in which to distinguish "empty" from "unknown yet". Closing it means deciding what a picker owes the primitive about the state of its own roster — a loading flag on the field, a tri-state roster, or a per-call-site gate that withholds the picker until the roster answers. That is a contract decision about the primitive's inputs, not a spelling change, and objectui#8488 is scoped to the rule itself.

Three points the decision should weigh:

  • The three loaders are not uniform: useDatasetSemantics already exposes loading and error, and DatasetNamesEditor at the same call site already consumes both, so ReportDefaultInspector has the signal on hand and does not pass it to the select. useObjectFields carries a loading in its state too.
  • objectui#5170 ruled on the neighbouring question for the SchemaForm widget family — a load FAILURE swallowed into an empty option list — and its answer was a dedicated PickerLoadFailure surface rather than a silent empty roster. The failure arm is handled there; the still-in-flight arm on the inspector primitive is what this card is about.
  • The damage is bounded and self-correcting (it clears when the response lands), which is why it is filed rather than fixed inside objectui#8488 — but the marker is a claim about the author's data, and it is briefly false.

Reproduction

Mount ViewColumnInspector on a variant bound to an object whose useObjectFields request is pending, with a column whose field key is a real field of that object. Read the field-key combobox's trigger text before the response resolves: it reads FIELDKEY (not in object).

Reference points

  • packages/app-shell/src/views/metadata-admin/inspectors/_shared.tsxInspectorSelectField, the isUnknownValue predicate
  • packages/app-shell/src/views/metadata-admin/inspectors/ViewColumnInspector.tsx — the field roster
  • packages/app-shell/src/views/metadata-admin/previews/useObjectFields.ts · previews/useDatasetCatalog.ts — the loaders that carry the missing signal
  • Related, distinct: objectui#8488 (the rule itself) - objectui#5170 (the load-FAILURE arm, SchemaForm widgets, already ruled)

Dedup

Ran. REST enumeration of every issue carrying package: app-shell (52 non-PR cards, open and closed, page 3 empty so the enumeration is closed) grepped over titles and bodies for the loading/roster shape: no match. One targeted semantic search_issues returned only objectui#5170, which is the load-failure arm on a different component family. The search channel's positive control in the same session returned objectui#8488 as its top hit, so the near-empty result is a reading and not a dead channel.


Generated by Claude Code

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatfindingpackage: app-shell

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions