fix: add null checks for foreignRecordMap in link field update methods#2667
Open
dkindlund wants to merge 1 commit intoteableio:developfrom
Open
fix: add null checks for foreignRecordMap in link field update methods#2667dkindlund wants to merge 1 commit intoteableio:developfrom
dkindlund wants to merge 1 commit intoteableio:developfrom
Conversation
When a desync exists between the JSONB cell values and the junction table (e.g., due to a prior concurrent update race condition), the foreignRecordMap may not contain all record IDs that appear in the toDelete/toAdd lists. This causes a TypeError crash: TypeError: Cannot read properties of undefined (reading '<fieldId>') The foreignRecordMap is built from JSONB cell values (via getRecordMapStruct), but toDelete/toAdd IDs come from the junction table (via getForeignKeys). When the JSONB is empty but the junction table has rows, records in toDelete are not loaded into foreignRecordMap. This fix adds null guards before accessing foreignRecordMap entries in the deletion/update branches of all four link field update methods: - updateForeignCellForManyMany - updateForeignCellForManyOne - updateForeignCellForOneMany - updateForeignCellForOneOne The addition branches already have null checks (throwing CustomHttpException), but the deletion branches did not, creating an asymmetry that could crash the server. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug Description
When a desync exists between the JSONB cell values and the junction table for many-to-many (or other) link fields, updating the link field via the API crashes with:
This happens because
foreignRecordMapis built from JSONB cell values (viagetRecordMapStruct), buttoDelete/toAddIDs come from the junction table (viagetForeignKeys). When the JSONB column is empty or out of sync with the junction table, records intoDeleteare not loaded intoforeignRecordMap, causing the undefined property access.The
toAddbranches already have null checks (throwingCustomHttpException), but thetoDelete/oldKeybranches do not — creating an asymmetry that crashes the server with an unhandled TypeError.Steps to Reproduce
77a8291d2)TypeError: Cannot read properties of undefinedHow the desync occurs in production:
Under concurrent load, multiple transactions can read the same JSONB snapshot, each compute their own version, and the last writer silently overwrites the others' changes (PostgreSQL
READ COMMITTEDdefault). Over time, the JSONB column falls behind the junction table. TheFOR UPDATElocking fix in commit77a8291d2prevents new desyncs, but does not fix existing ones — and this null check bug makes existing desync'd records permanently unrecoverable via the API.Expected Behavior
Updating a link field on a record with a JSONB/junction desync should not crash the server. The operation should either:
What This Fix Does
Adds null guards before accessing
foreignRecordMap[foreignRecordId]in the deletion/update branches of all four link field update methods:updateForeignCellForManyMany(toDelete loop)updateForeignCellForManyOne(oldKey loop)updateForeignCellForOneMany(toDelete loop + toAdd loop)updateForeignCellForOneOne(oldKey loop + newKey assignment)Client Information
main:latestcirca Oct 2025)Platform
Additional Context
77a8291d2("fix: fix link concurrent update"), which addedFOR UPDATErow-level locking. However, that fix only prevents new desyncs — it does not help with existing desync'd records, which remain permanently stuck because this null check bug prevents any API-based fix.