Skip to content

fix(tables): SSR crash from tableKeys in a 'use client' module + drop redundant flushChunks#5204

Merged
waleedlatif1 merged 3 commits into
stagingfrom
fix/tables-querykey-ssr
Jun 25, 2026
Merged

fix(tables): SSR crash from tableKeys in a 'use client' module + drop redundant flushChunks#5204
waleedlatif1 merged 3 commits into
stagingfrom
fix/tables-querykey-ssr

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

Two fixes, both off staging:

1. Tables list crash at SSR (regression from #5196)

The tables list page failed to load in staging with:

TypeError: i.tableKeys.list is not a function
  (In 'i.tableKeys.list(b, "active")', 'i.tableKeys.list' is undefined)
  at .next/server/chunks/ssr/[root-of-the-server]

Cause: tables/prefetch.ts is a server component, but it imported tableKeys from hooks/queries/tables.ts, which carries 'use client'. When a server module imports from a 'use client' module, Next.js replaces the export with a client-reference stub in the server bundle — so tableKeys.list is undefined at SSR. (The other three prefetch pages were fine because their key factories live in non-'use client' modules, e.g. folder-keys.ts.)

Fix: Extract the key factory into hooks/queries/utils/table-keys.ts (no 'use client'), mirroring the existing folder-keys.ts pattern, and import it from there in the prefetch, the hook, the table trigger/poller, and the two consumers. tables.ts now imports the factory instead of defining it.

2. Redundant flushChunks() on the SSE error path (chat.tsx)

Addresses a Greptile P2 from the release PR. On an error final event the reader stops (return true), so the post-loop flush is the single flush point. Defer the error append to after that flush — single flush, correct ordering — instead of flushing inside onEvent and again post-loop. No behavior change.

Type of Change

  • Bug fix (SSR crash) + minor refactor

Testing

  • prefetch.test.ts (9 tests) green; tsc 0 errors; Biome clean; check:react-query passes.
  • The SSR fix mirrors the proven folder-keys.ts pattern (pure non-'use client' module); CI's "Test and Build" exercises the real next build/SSR path.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel

vercel Bot commented Jun 25, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jun 25, 2026 12:31am

Request Review

@cursor

cursor Bot commented Jun 25, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Targeted SSR import split and small SSE/chat ordering fixes; keys are unchanged and tests cover the new SSE tail behavior.

Overview
Fixes a staging SSR crash on the tables list (tableKeys.list is not a function) by moving the React Query key factory out of hooks/queries/tables.ts into a new hooks/queries/utils/table-keys.ts (no 'use client'), matching folder-keys.ts. Server prefetch and other callers now import the real factory instead of a Next.js client-reference stub.

Workflow chat streaming: failed final SSE events no longer call flushChunks() inside onEvent; the error is stored and appended after the post-loop flush so chunk batching stays single-flush.

SSE reader: readSSELines now decodes and processes the last partial line when the stream ends (final data: without a trailing newline), with new tests for stream-tail and multi-byte UTF-8 cases.

Reviewed by Cursor Bugbot for commit dc1cf47. Configure here.

@greptile-apps

greptile-apps Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes two independent regressions introduced in #5196: an SSR crash caused by importing tableKeys from a 'use client' module in a server component, and a silent data-loss bug in readSSELines that dropped the final SSE line when it lacked a trailing newline.

  • SSR crash fix: tableKeys and TableQueryScope are extracted into a new hooks/queries/utils/table-keys.ts (no 'use client'), mirroring folder-keys.ts. All five consumers updated to import from the new location.
  • SSE decoder fix: readSSELines now flushes the TextDecoder and processes the final unterminated line when done=true. Two new tests cover a plain single-line tail and a split multi-byte character.
  • Chat error path cleanup: The redundant flushChunks() inside onEvent is removed; the error append is deferred until after the single post-loop flush.

Confidence Score: 5/5

Safe to merge — both fixes are narrowly scoped, mechanically correct, and backed by new tests.

The table-keys.ts extraction is a pure refactor with no logic changes; TypeScript enforces that all consumers updated correctly. The readSSELines change is a targeted loop-order fix with two purpose-built tests that directly exercise the previously broken path. The chat error deferral eliminates a double-flush with no observable behavior change.

No files require special attention.

Important Files Changed

Filename Overview
apps/sim/hooks/queries/utils/table-keys.ts New standalone non-use-client key factory, an exact mirror of the removed definition in tables.ts
apps/sim/lib/core/utils/sse.ts Fixes readSSELines to flush the TextDecoder and process the final unterminated SSE line instead of silently dropping it when done=true
apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/chat/chat.tsx Defers error message append to after the single post-loop flushChunks(), eliminating the redundant in-event flush
apps/sim/app/workspace/[workspaceId]/tables/prefetch.ts Import updated from use-client tables.ts to the new standalone table-keys.ts, fixing the SSR crash
apps/sim/hooks/queries/tables.ts Removed tableKeys definition and TableQueryScope type, now imported from utils/table-keys.ts; no logic changes

Reviews (2): Last reviewed commit: "fix(sse): process the final unterminated..." | Re-trigger Greptile

…h works

The tables list page crashed at SSR ('tableKeys.list is not a function') because
tables/prefetch.ts (a server component) imported tableKeys from
hooks/queries/tables.ts — a 'use client' module whose exports resolve to
client-reference stubs on the server. Extract the key factory into
hooks/queries/utils/table-keys.ts (no 'use client'), mirroring folder-keys.ts,
and import it from there in the prefetch, hook, trigger, and consumers.
On an error 'final' event the reader stops via return true, so the post-loop
flush is the single flush point. Defer the error append to after that flush
(single flush, correct ordering) instead of flushing inside onEvent and again
post-loop. No behavior change.
readSSELines broke out of the read loop on 'done' without flushing the
TextDecoder or processing the trailing buffer, so a final 'data:' line not
terminated by a newline (and any buffered multi-byte character) was dropped.
Flush the decoder on end-of-stream and process the remaining buffer.
Addresses a Cursor Medium finding on the consolidated SSE reader.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile review

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit dc1cf47. Configure here.

@waleedlatif1 waleedlatif1 merged commit c3a0969 into staging Jun 25, 2026
16 checks passed
@waleedlatif1 waleedlatif1 deleted the fix/tables-querykey-ssr branch June 25, 2026 00:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant