Skip to content

Every workspace crashes with workspacePages.map is not a function #7758

Closed

Description

@dvoytenko

Where did this happen?

Desktop app (macOS)

Version

1.30.2

What happened?

Superset 1.30.2: opening any workspace crashes in selectMenuPages.ts:43, called by WorkspacePagesMenu.tsx:66. workspacePages contains { items: [], nextCursor: null }, but the selector calls workspacePages.map(...), expecting an array.

The stack trace:

Content route error caught: TypeError: workspacePages.map is not a function
    at selectMenuPages (selectMenuPages.ts:43:4)
    at WorkspacePagesMenu.tsx:66:4
    at Object.useMemo (react-dom-client.production.js:5518:23)
    at react_production.useMemo (react.production.js:514:33)
    at WorkspacePagesMenu (WorkspacePagesMenu.tsx:64:40)

Steps to reproduce

  1. Open workspace
  2. See failure

Logs, screenshots, or recordings

Image

Activity

  1. github-actions commented on Sep 23, 2026

    @github-actions
    Contributor

    This looks like the server-side regression that the latest commit on main already fixes: 4c56a68, "fix(pages): restore page.list's bare-array contract for released clients (#7756)". Nothing needs to change in the desktop app. Once the API with that commit is deployed, 1.30.2 should stop crashing.

    Summary

    Opening any workspace in desktop 1.30.2 crashes with TypeError: workspacePages.map is not a function in selectMenuPages. The value passed in is { items: [], nextCursor: null }, which is a paginated response, but the 1.30.2 code expects a plain array. The cloud API's page.list procedure was changed to return { items, nextCursor }, and released clients still call page.list expecting the plain array it used to return. A client that has already shipped can't be updated from the server side, so every workspace view that renders WorkspacePagesMenu hits the error and the route's error screen replaces the content.

    Affected code

    Server (cloud tRPC API):

    • packages/trpc/src/router/page/page.ts:461-483: page.list now loops through listPageBatch until there's no cursor left, then returns the plain array (return all;). This is the fix(pages): restore page.list's bare-array contract for released clients #7756 fix.
    • packages/trpc/src/router/page/page.ts:485-493: the paginated shape ({ items, nextCursor }, built at page.ts:311-374) now has its own procedure, page.listPaginated.
    • packages/trpc/src/router/page/schema.ts:125-131: legacyListPagesSchema keeps the old input ({ workspaceId? }). The comment above it notes that released desktop, mobile and CLI builds still depend on the plain array.

    Desktop, current main (already on the new procedure):

    • apps/desktop/src/renderer/routes/_authenticated/_dashboard/hooks/usePagesList/usePagesList.ts:17-63 calls page.listPaginated.useInfiniteQuery and flattens the results into items.
    • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/components/WorkspacePagesMenu/WorkspacePagesMenu.tsx:80-87 passes workspacePagesQuery.items into selectMenuPages.
    • .../WorkspacePagesMenu/utils/selectMenuPages/selectMenuPages.ts:42-43 calls workspacePages.map(...) with no guard. This is the crash site in the stack trace.

    Suspected root cause

    When 1.30.2 shipped, WorkspacePagesMenu got its data from page.list and passed the result to selectMenuPages as an array. A later server change made page.list return { items, nextCursor }, which broke the tRPC contract for every client already in users' hands. The object reached selectMenuPages.ts:43 and .map failed. The versions line up: the payload in the report, { items: [], nextCursor: null }, matches the object listPageBatch builds at page.ts:374.

    #7756 puts the plain array back on page.list and moves pagination to page.listPaginated, which is the right way to fix a contract break with released clients. If users still see the crash after that commit is deployed, the likely cause is caching or a deploy that hasn't gone out yet, not a new bug.

    The same break probably hit other released clients that call page.list: mobile's usePages and the CLI's pages list. The schema comment names both.

    Reproduction

    1. Run desktop 1.30.2 against an API build from before 4c56a68.
    2. Open any v2 workspace. The pages menu mounts, page.list returns { items, nextCursor }, and selectMenuPages throws.
    3. Point the same client at an API built from 4c56a68 or later and the workspace should open normally.

    Suggested follow-ups

    • Confirm the deploy. Check that the API with 4c56a68 is in production, then close this issue.
    • Add a contract test. Nothing in packages/trpc/src/router/page/ checks that page.list returns an array (list.integration.ts only covers the paginated batches). A small integration test would stop this happening again:
      test("page.list returns a bare array for released clients", async () => {
        const result = await caller.page.list({ workspaceId });
        expect(Array.isArray(result)).toBe(true);
      });
    • Optional hardening: selectMenuPages could fail soft on unexpected input so one bad payload doesn't take down the whole workspace route. The real fix is keeping the API contract stable for released clients, though, not guarding every consumer.
  2. saddlepaddle commented on Sep 23, 2026

    @saddlepaddle
    Collaborator

    This now should be resolved if you cmd+R, apologies for the issue!

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 working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions