Skip to content

The same records-before-data tolerant reader survives in ~7 more find() consumers that #5945 did not name #6726

Description

@os-sales

Found while implementing #5945 (out of that card's scope — it names exactly two call sites).

The shape

#5945 reduced the asArray helpers in packages/app-shell/src/hooks/useApproverDirectory.ts and packages/app-shell/src/views/metadata-admin/AssignedUsersSection.tsx to the one rows member QueryResult declares (data), after measuring that nothing produces records or items at the DataSource.find() seam.

The producer sweep that established that also turned up the same tolerant read, on the same seam, in modules the card did not name. Each of these consumes an adapter.find() / dataSource.find() answer and reads records — a key QueryResult does not declare:

  • packages/components/src/hooks/related-count-store.ts:110Array.isArray(res?.records) ? res.records.length : Array.isArray(res?.data) ? res.data.length : .... records is tried before data, the same precedence inversion asArray helpers read three result shapes, two of which are not QueryResult members — a tolerant reader standing in for the contract #5945 fixed.
  • packages/components/src/renderers/basic/data-list.tsx:140res?.data ?? res?.records ?? (Array.isArray(res) ? res : [])
  • packages/components/src/renderers/basic/elements.tsx:427 — same chain
  • packages/components/src/renderers/basic/record-picker.tsx:146 — same chain
  • packages/plugin-detail/src/renderers/record-activity.tsx:186res?.data ?? res?.records ?? []
  • packages/plugin-detail/src/renderers/record-history.tsx:90res?.data ?? res?.records ?? []
  • packages/plugin-view/src/ObjectView.tsx:930else if (Array.isArray((results as any).records)) { items = (results as any).records; }

Most of these read data first, so the records arm is dead rather than actively wrong. related-count-store.ts is the exception and the one worth looking at first: it reads recordsahead ofdata, which is exactly the ordering #5945 was filed about.

Why it is worth recording

QueryResult (packages/types/src/data.ts) declares data, total, page, pageSize, hasMore, cursor, metadata. records is not a member. It is the spelling the server envelope and the client SDK use, which ObjectStackAdapter.normalizeQueryResult maps to data before returning — so it is a below-the-adapter spelling that has leaked into above-the-adapter consumers.

This is AGENTS.md #0.1: every extra arm is a place a non-conforming producer would keep working unrejected. #5945's own history is the argument — the same records/items confusion was live in three places #5458 had to fix, each reading a key no adapter returns, and the tolerant helpers are why nobody found out.

Not included, deliberately

Two other records readers are on different seams and are likely correct as they stand — worth confirming rather than assuming:

  • packages/app-shell/src/console/marketplace/marketplaceApi.ts:354,403 and packages/app-shell/src/views/setup/packagedActions.ts:108 read a raw HTTP payload, not a QueryResult.
  • packages/core/src/data-scope/ViewDataProvider.ts returns its own ResolvedData interface, which declares records legitimately.

Suggested shape

Per module, the same two-step #5945 used: measure whether any producer emits the key at that seam, then delete the arm if none does and pin the contract read. ⛔ Do not widen QueryResult to bless records — that is a published-type change and a maintainer decision.

Metadata

Metadata

Assignees

Labels

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

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions