fix: solve #5852 — chat pane FK violation inserting chat_sessions.v2_workspace_id for local-first workspaces

Draft
GI
4mo ago
+144-2

Root cause

chat.createSession (packages/trpc/src/router/chat/chat.ts) inserted chat_sessions.v2_workspace_id directly from the client-supplied input.v2WorkspaceId. That column has an FK to cloud v2_workspaces (chat_sessions_v2_workspace_id_v2_workspaces_id_fk).

Post local-first migration, v2 workspaces are authored in host.db and the electric-synced cloud v2_workspaces table can be empty for the org (0 rows) while the desktop runs several local workspaces. The FK can therefore never be satisfied: the insert throws and the raw DrizzleQueryError surfaces in the chat pane on every message. The older REST route (apps/api/src/app/api/chat/[sessionId]/route.ts) already has a retry-without-workspaceId fallback for this exact failure class; the tRPC path had none.

The fix

Before inserting, verify the workspace exists cloud-side and only pin v2_workspace_id when it does; otherwise persist NULL — mirroring the REST route's shouldRetryWithoutWorkspaceId behavior (option (a) from the issue).

The check is done up front inside the transaction rather than as catch-and-retry, because a failed INSERT aborts the surrounding Postgres transaction (current transaction is aborted…), which would make an in-transaction retry fail regardless. A SELECT returning zero rows leaves the transaction usable.

Tests

Added packages/trpc/src/router/chat/chat.test.ts:

  • reproduction — with the cloud v2_workspaces set empty (local-first), the mock insert faithfully models the FK and throws the reported error. Before the fix createSession rejected with the raw SQL; after the fix it falls back to v2_workspace_id = NULL and returns the session id.
  • regression guard — when the workspace does exist cloud-side, its id is preserved.

Both pass; packages/trpc typechecks and lints clean.

Note: the issue also suggests catching this in ChatPane to show a human-readable message instead of raw SQL. That is left out of this scoped fix since the FK violation no longer occurs on the happy path; it can be a follow-up for defense-in-depth.

Closes #5852


Summary by cubic

Prevent FK violations when creating chat sessions by verifying v2_workspace_id against cloud v2_workspaces and inserting NULL when missing. Fixes chat pane errors for local-first workspaces and aligns tRPC with the REST fallback (closes #5852).

  • Bug Fixes
    • In packages/trpc/src/router/chat/chat.ts, check for the workspace in v2Workspaces inside the transaction; only set v2_workspace_id when it exists, else persist NULL.
    • Avoid catch-and-retry since a failed insert aborts the transaction; use a pre-insert SELECT instead.
    • Added packages/trpc/src/router/chat/chat.test.ts covering local-first fallback and cloud-present cases.