From fa8304d323e3af6cb39eecaa36b362c3efe18006 Mon Sep 17 00:00:00 2001 From: Abdul Rahman <81605929+abdulrahmancodes@users.noreply.github.com> Date: Mon, 4 May 2026 15:27:21 +0530 Subject: [PATCH] Fix record table dashboard save (#20202) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Fixes `METADATA_VALIDATION_FAILED` / “view field already exists” when saving dashboard **record table** widgets after the first persist (e.g. several table widgets on one dashboard). ## Problem Draft view columns used **client-generated** `viewField` ids. After save, the API stored **different** ids. The next upsert still sent the old draft ids as `viewFieldId`. The server only matched on that id, missed every row, and tried to **create** columns that already existed for the same `fieldMetadataId` + view. --- .../hooks/useSaveRecordTableWidgetViews.ts | 1 - .../services/view-widget-upsert.service.ts | 19 +++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/twenty-front/src/modules/page-layout/hooks/useSaveRecordTableWidgetViews.ts b/packages/twenty-front/src/modules/page-layout/hooks/useSaveRecordTableWidgetViews.ts index b4e55c8464..5e3d83b0e7 100644 --- a/packages/twenty-front/src/modules/page-layout/hooks/useSaveRecordTableWidgetViews.ts +++ b/packages/twenty-front/src/modules/page-layout/hooks/useSaveRecordTableWidgetViews.ts @@ -65,7 +65,6 @@ export const useSaveRecordTableWidgetViews = () => { input: { widgetId: widget.id, viewFields: widgetViewDraft.viewFields.map((field) => ({ - ...(isDefined(field.id) ? { viewFieldId: field.id } : {}), fieldMetadataId: field.fieldMetadataId, isVisible: field.isVisible, position: field.position, diff --git a/packages/twenty-server/src/engine/metadata-modules/view/services/view-widget-upsert.service.ts b/packages/twenty-server/src/engine/metadata-modules/view/services/view-widget-upsert.service.ts index 3270c9d561..bf7fb0885a 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view/services/view-widget-upsert.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view/services/view-widget-upsert.service.ts @@ -383,13 +383,20 @@ export class ViewWidgetUpsertService { const fieldsToUpdate: FlatViewField[] = []; for (const inputField of inputFields) { - const existingField = isDefined(inputField.viewFieldId) + const existingFieldByViewFieldId = isDefined(inputField.viewFieldId) ? existingViewFields.find((f) => f.id === inputField.viewFieldId) - : isDefined(inputField.fieldMetadataId) - ? existingViewFields.find( - (f) => f.fieldMetadataId === inputField.fieldMetadataId, - ) - : undefined; + : undefined; + + const existingFieldByFieldMetadataId = isDefined( + inputField.fieldMetadataId, + ) + ? existingViewFields.find( + (f) => f.fieldMetadataId === inputField.fieldMetadataId, + ) + : undefined; + + const existingField = + existingFieldByViewFieldId ?? existingFieldByFieldMetadataId; if (isDefined(existingField)) { const resolvedIsVisible = isDefined(existingField.overrides?.isVisible)