From 36e89c04ad160914d84e64ac1215b83a8c6a6c12 Mon Sep 17 00:00:00 2001 From: Paul Rastoin <45004772+prastoin@users.noreply.github.com> Date: Tue, 30 Jun 2026 17:26:22 +0200 Subject: [PATCH] Front fallback flat object search field metadata (#22369) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Fix: crash on Settings → Object → Search after changing label identifier ### Problem Opening the Search section (or changing an object's label identifier) threw `t.searchFieldMetadatas is not iterable` in `SettingsObjectSearchSection`. ### Root cause `EnrichedObjectMetadataItem.searchFieldMetadatas` is typed as a non-optional array, but at runtime it can be `undefined`. `useLoadMinimalMetadata` stores the minimal objects with `objectMetadataItems as unknown as FlatObjectMetadataItem[]`. The minimal query doesn't select `searchFieldMetadataList`, so the double-cast hides that the property is missing. Until the full metadata reload lands, the object has no `searchFieldMetadatas`, and `objectMetadataItemsWithFieldsSelector` spreads that `undefined` straight through to the component, which spreads it (`[...searchFieldMetadatas]`) and crashes. (`fields`/`indexMetadatas` never hit this because they come from `Map.get()`, which is honestly typed as `| undefined` and already falls back to `[]`.) ### Fix Guarantee the array contract in `objectMetadataItemsWithFieldsSelector`, matching how `fields`/`indexMetadatas` are already defaulted: `searchFieldMetadatas: flatObject.searchFieldMetadatas ?? []`. ### Tradeoff considered The "clean" alternative is promoting `searchFieldMetadatas` to its own metadata-store entity (like `indexMetadataItems`), which would make the `?? []` type-mandated via `Map.get`. Rejected for now: it's a medium cross-package refactor (new store key, type, selectors, split/reload wiring, plus a server-side collection hash for staleness) for an entity that is never independently mutated — it only changes as a side effect of label-identifier/field updates, so independent caching buys nothing. The selector default fixes the crash with minimal surface area; the deeper cleanup (making the `as unknown as` cast honest, or splitting the store) can be deferred until search-field metadata becomes directly editable. --- .../states/objectMetadataItemsWithFieldsSelector.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/twenty-front/src/modules/object-metadata/states/objectMetadataItemsWithFieldsSelector.ts b/packages/twenty-front/src/modules/object-metadata/states/objectMetadataItemsWithFieldsSelector.ts index a03f2ca3db..02072d09b2 100644 --- a/packages/twenty-front/src/modules/object-metadata/states/objectMetadataItemsWithFieldsSelector.ts +++ b/packages/twenty-front/src/modules/object-metadata/states/objectMetadataItemsWithFieldsSelector.ts @@ -83,6 +83,7 @@ export const objectMetadataItemsWithFieldsSelector = createAtomSelector< ...flatObject, fields, indexMetadatas, + searchFieldMetadatas: flatObject.searchFieldMetadatas ?? [], readableFields: fields.filter( (field) => !nonReadableFieldMetadataIds.includes(field.id), ),