From a1b22b65e66a8b74032903c705a57412c5818b74 Mon Sep 17 00:00:00 2001 From: Sonarly Claude Code Date: Wed, 18 Feb 2026 22:13:10 +0000 Subject: [PATCH] fix: gracefully handle unknown fields in SSE optimistic record updates When SSE events include custom fields not present in the client-side object metadata (e.g. user-defined fields on Opportunity), the computeOptimisticRecordFromInput function was throwing a fatal error that broke the entire SSE event stream processing. Since the function's for-loop already only processes known metadata fields, unknown fields in the record input are naturally skipped. Replace the throw with a console.warn so processing continues gracefully. Co-Authored-By: Claude Opus 4.6 --- .../computeOptimisticRecordFromInput.test.ts | 42 +++++++++++-------- .../utils/computeOptimisticRecordFromInput.ts | 4 +- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/utils/__tests__/computeOptimisticRecordFromInput.test.ts b/packages/twenty-front/src/modules/object-record/utils/__tests__/computeOptimisticRecordFromInput.test.ts index 2f79abe0357..4c947f833c7 100644 --- a/packages/twenty-front/src/modules/object-record/utils/__tests__/computeOptimisticRecordFromInput.test.ts +++ b/packages/twenty-front/src/modules/object-record/utils/__tests__/computeOptimisticRecordFromInput.test.ts @@ -233,26 +233,34 @@ describe('computeOptimisticRecordFromInput', () => { }); }); - it('should throw an error if recordInput contains fields unrelated to the current objectMetadata', () => { + it('should warn and skip unknown fields if recordInput contains fields unrelated to the current objectMetadata', () => { const cache = new InMemoryCache(); const personObjectMetadataItem = getMockPersonObjectMetadataItem(); + const consoleWarnSpy = jest + .spyOn(console, 'warn') + .mockImplementation(() => {}); - expect(() => - computeOptimisticRecordFromInput({ - currentWorkspaceMember, - objectMetadataItems: generatedMockObjectMetadataItems, - objectMetadataItem: personObjectMetadataItem, - recordInput: { - unknwon: 'unknown', - foo: 'foo', - bar: 'bar', - city: 'Paris', - }, - cache, - objectPermissionsByObjectMetadataId: {}, - }), - ).toThrowErrorMatchingInlineSnapshot( - `"Should never occur, encountered unknown fields unknwon, foo, bar in objectMetadataItem person"`, + const result = computeOptimisticRecordFromInput({ + currentWorkspaceMember, + objectMetadataItems: generatedMockObjectMetadataItems, + objectMetadataItem: personObjectMetadataItem, + recordInput: { + unknwon: 'unknown', + foo: 'foo', + bar: 'bar', + city: 'Paris', + }, + cache, + objectPermissionsByObjectMetadataId: {}, + }); + + expect(consoleWarnSpy).toHaveBeenCalledWith( + expect.stringContaining('encountered unknown fields'), ); + expect(result).toEqual({ + city: 'Paris', + }); + + consoleWarnSpy.mockRestore(); }); }); diff --git a/packages/twenty-front/src/modules/object-record/utils/computeOptimisticRecordFromInput.ts b/packages/twenty-front/src/modules/object-record/utils/computeOptimisticRecordFromInput.ts index ec19e8eb083..a1ad08fed5a 100644 --- a/packages/twenty-front/src/modules/object-record/utils/computeOptimisticRecordFromInput.ts +++ b/packages/twenty-front/src/modules/object-record/utils/computeOptimisticRecordFromInput.ts @@ -69,8 +69,8 @@ export const computeOptimisticRecordFromInput = ({ }, ); if (unknownRecordInputFields.length > 0) { - throw new Error( - `Should never occur, encountered unknown fields ${unknownRecordInputFields.join(', ')} in objectMetadataItem ${objectMetadataItem.nameSingular}`, + console.warn( + `computeOptimisticRecordFromInput: encountered unknown fields ${unknownRecordInputFields.join(', ')} in objectMetadataItem ${objectMetadataItem.nameSingular}. Skipping unknown fields.`, ); }