Skip to content

console: changing the command-palette query after record hits have loaded blanks the whole console (cmdk "Cannot read properties of undefined (reading 'forEach')") #13387

Closed

Description

@marchtian

Requested by 田騏 · project thread

Found during an exploratory walkthrough of the showcase app.

Environment

  • objectui main @ 6fb31dc, console served by pnpm --filter @object-ui/console dev (:5180)
  • objectstack main @ b9c7a8f, PORT=3000 pnpm dev (showcase), signed in as the dev admin, locale zh-CN
  • Chromium (Playwright), 1440×900

Steps

  1. Open any app page, e.g. /apps/com.example.showcase/showcase_task.
  2. Press Ctrl/⌘+K and type Website. Wait for the record hits (a 项目 group with Website Relaunch).
  3. Change the query to something that returns a different set of record groups, either by select-all + typing 华宁 / Co, or by deleting the text with Backspace and typing Contoso.

Expected

The palette shows the hits for the new query.

Actual

The palette disappears and the entire console unmounts to an empty page (no shell, no sidebar); only a reload recovers. The page error is:

TypeError: Cannot read properties of undefined (reading 'forEach')
    at .../node_modules/.vite/deps/cmdk.js:139:6
    at Set.forEach (<anonymous>)
    at z (.../cmdk.js:137:29)
    at .../cmdk.js:106:5
    at .../cmdk.js:483:28
    at Map.forEach (<anonymous>)
    ...commitHookEffectListMount (react-dom_client.js)

followed by React's "An error occurred in the component. Consider adding an error boundary…".

Reproduced on every attempt (2/2 for each of the sequences above). A fresh query typed into a newly opened palette works (华宁, hn, Contoso, Data, 设置 all fine), and so does extending a query (Web → Website). It is the switch from one record-group set to another that crashes.

Reading of the cause (from the stack and the bundled cmdk 1.1.1 source, not debugged further)

cmdk's sort step (z in the minified build) walks state.filtered.groups and, for each id, reads that group's item set from its group map and calls .forEach on it. A CommandGroup that unmounts deletes its own map entry. In CommandPalette.tsx the record hits are rendered as one CommandGroup per object, keyed records:<objectName>, so when the new query stops returning an object that group unmounts while filtered.groups still names it, and the sort scheduled by an item's value change runs before the filter is recomputed. The lookup returns undefined and throws inside a layout effect.

Two separate things make it worse than a broken palette:

  • nothing above the palette catches the error, so one bad search takes down the whole console;
  • the record-group set is exactly the part of the palette that changes on every query, so ordinary use hits it.

Suggested direction

Make the record groups stable across queries (or let the async record hits bypass cmdk's own sort/filter, since their order and membership already come from /api/v1/search), and put an error boundary around the palette so a palette failure cannot unmount the shell.

Activity

  1. marchtian commented on Oct 23, 2026

    @marchtian
    CollaboratorAuthor

    Not a regression: this also reproduces on the released 18.0.0 console.

    I reproduced it on the prebuilt @objectstack/console@18.0.0 from npm. Its dist/.objectui-sha is 616df6598b429d2b3687301a2041198928e68971. I served it same-origin, in front of the same objectstack main showcase backend, and signed in as the dev admin. Both sequences in the issue crash it the same way (2/2), with the same pageerror: Cannot read properties of undefined (reading 'forEach').

    Between 616df6598 and 6fb31dcc9:

    The per-object record groups (key={records:${group.objectName}}) were added in 8ecf5a6 (#2772, 2026-07-21), when the palette started showing /api/v1/search hits. That is most likely where the crash comes from. I have not bisected it build by build.


    Generated by Claude Code

  2. added
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    on Oct 23, 2026
  3. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    Contributor

    Triage: lands in apps/console CommandPalette.tsx (the per-object records:<objectName> CommandGroups) plus an error boundary around the palette in the shell; rationale: ordinary use of ⌘K (changing the query) unmounts the whole console. Not a regression: the filer reproduced it on the released 18.0.0 console (.objectui-sha 616df65), most likely since #2772 added per-object record groups. Two parts: make the async record groups bypass cmdk's own sort/filter (or keep them stable across queries), and contain any palette failure so it cannot take the shell down.
    Path: records · 搜得到…全局搜索与命令面板同一条路 | search.console-global-search (P1, fails on a changed query) | step ②
    Grade: priority:p1 — inherits the P1 item, which fails; a whole-app white screen on a common action. Not P0: a reload recovers and nothing is lost. Release: it already ships in 18.0.0, so it does not make 18.1.0 worse; whether it holds the 18.1.0 cut is the maintainer's call, raised in the project thread.
    Type: Bug

    Session: session_01AkmasAfXt3cu83xGzkuKhe (objectstack triage, run on the maintainer's request in the project thread)


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    Contributor

    Claim: project thread seat (maintainer-dispatched) at 2026-10-23T17:20Z
    Session: session_01Qfcwdm3pMxUcQjYXXJxRNt
    Account: marchtian (the seat's linked user; the card's assignee)
    Branch: claude/project-thread-zt8k65
    Worktree: objectui-13387
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: packages/app-shell/src/chrome/ (CommandPalette.tsx plus one new test file beside it), one .changeset/*.md
    Container & model: S, mode:thread, model: TIER_DEFAULT (dispatch-gates --tier --repo objectstack-ai/objectui: no path-derived mandate), effort: xhigh (p1)
    Clause-②: no
    Metadata-protocol: none
    Responsibility: objectui app-shell CommandPalette: per-object record CommandGroups fed to cmdk's own sort/filter | none: nothing above the palette catches a render-phase or layout-effect error | every console user who changes a ⌘K query after record hits load; ordinary use today
    Thread-read: 6370061042
    Serial constraints cleared: none (no open PR touches CommandPalette.tsx or the palette; searched repo:objectstack-ai/objectui is:open CommandPalette and palette)

    Dispatch provenance: the maintainer (田騏) ruled on the release decision card in the project thread, 2026-10-23T17:15Z, verbatim: 「不挡,现在就派人修」. This card does not block 18.1.0 and is worked now.

    Plan, as the triage comment scopes it:

    1. The palette already matches every entry it renders itself (matchesPaletteQuery), and record hits come ranked from /api/v1/search, so cmdk's own filter and sort are turned off (shouldFilter={false}). The crash is cmdk's sort walking a group id that an unmounted per-object group has already removed; with its filter off that sort never runs.
    2. A palette failure is contained: an error boundary around the palette closes it and leaves the shell mounted, so the next ⌘K opens a fresh one.
    3. A test reproduces the query switch between two different record-group sets.

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    Contributor

    Ruled (maintainer, 2026-10-23, decision card in the project thread, option A verbatim): 「不挡,现在就派人修」 — do not hold 18.1.0 for this card; dispatch it now.

    Session: session_01AkmasAfXt3cu83xGzkuKhe (objectstack triage, relaying the maintainer's ruling)


    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:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p1

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions