Repository navigation
fix(replication): guard copy cursor write against undefined table name - #322
Conversation
If the last event decoded in a copy frame has no table name (event.table is undefined), the persisted copyCursor would store currentTable: undefined. On every subsequent reconnect the leader checks tables[copyResume.currentTable] — tables[undefined] is always falsy — and the full copy restarts from zero, defeating the resumable-copy feature entirely (#255). Add event.table to the cursor-write guard so a batch whose final decoded event carries no table name leaves the existing (valid) cursor in place instead of overwriting it with an invalid one. A warn log fires in that case to surface the underlying cause. Fixes #321. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Reviewed; no blockers found. Summary: Two-commit PR. The core fix ( Core fix observations:
Stress-test cleanup:
No security, auth, or API contract concerns. |
There was a problem hiding this comment.
Code Review
This pull request updates the replication connection logic to prevent advancing the copy cursor if the event is missing a table name, and adds a warning log for this scenario. The reviewer suggested removing the copyFromNodeId !== undefined check from the warning condition to ensure the diagnostic log is always captured when an event lacks a table name.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| } else if (isCopyFrame && event && !event.table && copyFromNodeId !== undefined) { | ||
| logger.warn?.(connectionId, 'copy cursor not advanced: event has no table name', databaseName); | ||
| } |
There was a problem hiding this comment.
The else if block is intended to log a warning when an event is missing its table name during a copy frame, which is a key diagnostic for debugging the root cause of this issue. However, by requiring copyFromNodeId !== undefined in the else if condition, this warning will be silently skipped if copyFromNodeId happens to be undefined.
Since event.table being missing is an unexpected decoder anomaly, we should log this warning regardless of whether copyFromNodeId is valid. Removing the copyFromNodeId !== undefined check from the else if condition ensures we always capture this diagnostic log.
| } else if (isCopyFrame && event && !event.table && copyFromNodeId !== undefined) { | |
| logger.warn?.(connectionId, 'copy cursor not advanced: event has no table name', databaseName); | |
| } | |
| } else if (isCopyFrame && event && !event.table) { | |
| logger.warn?.(connectionId, 'copy cursor not advanced: event has no table name', databaseName); | |
| } |
The function was defined but its logic is duplicated inline in the test's polling loop. This caused a lint error blocking CI. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary
One-line guard change in the bulk-copy resume path to prevent persisting a cursor with
currentTable: undefined.What this fixes
When the last decoded event in a copy frame has no table name (
event.tableisundefined), the previous guardif (isCopyFrame && event && ...)still passes (the event object is truthy) and writescurrentTable: undefinedto the persistedcopyCursor. On every subsequent reconnect the leader evaluatestables[copyResume.currentTable]→tables[undefined]is always falsy, which triggers the "Copy-resume table missing or unreplicated, restarting full copy" path and restarts from zero — completely defeating the resumable-copy feature (#255).Change:
event &&→event?.table &&, with anelse ifwarn log when we have an event but no table name to help surface the underlying cause (why a decoded event has no table name is still an open question in #321).Closes #321. Reported in Slack thread (spectrum-et cluster on 5.1.0-beta.2, system DB 800M+, copy looping endlessly with 67 MB SSTs landing each cycle but never finalizing).
What to look at
replication/replicationConnection.ts~line 2100. The warn branch is the only new code worth scrutiny.event.tablebeingundefinedis still unknown. The fix prevents the corrupted cursor; the warn log will surface instances in logs so we can trace it.Generated by claude-sonnet-4-6