From cc1145c701a0cd80c9e93e047cae801504a87ccd Mon Sep 17 00:00:00 2001 From: "sonarly[bot]" <251243324+sonarly[bot]@users.noreply.github.com> Date: Fri, 20 Feb 2026 08:27:53 +0000 Subject: [PATCH] Fix: Person avatar upload fails with unknown field error (#18109) ## Automated fix for [bug None](https://sonarly.com/issue/None?type=bug) **Severity:** `critical` ### Summary When uploading a person avatar with the new FILES field migration enabled, the optimistic record validation in computeOptimisticRecordFromInput throws because the avatarFile field may not be recognized in the person object metadata, crashing the upload flow. ### User Impact Users with the IS_FILES_FIELD_MIGRATED feature flag enabled cannot upload or change a person's avatar photo. The upload operation throws an unhandled error, preventing the avatar update from completing. ### Root Cause The usePersonAvatarUpload hook passes avatarFile as a field in updateOneRecordInput when calling updateOneRecord. This input goes through computeOptimisticRecordFromInput, which validates that every field in the record input exists in objectMetadataItem.fields. The avatarFile field (type FILES) was recently added as a standard field on the person object, but may not yet be present in the frontend's cached object metadata for all workspaces (e.g., workspaces where the metadata has not been synced after the migration, or SSE events arriving before metadata refresh). When avatarFile is not found in the metadata fields array, the validation throws. The useUpdateOneRecord hook supports an optimisticRecord parameter that bypasses this validation entirely, but usePersonAvatarUpload did not provide it. Introduced by Etienne in commit d0c1841f0f8 on 2026-02-11, which added the avatar file migration and upload logic but did not supply an optimisticRecord to bypass the strict field validation in computeOptimisticRecordFromInput. **Introduced by:** Etienne on 2026-02-11 in commit [`d0c1841`](https://github.com/twentyhq/twenty/commit/d0c1841f0f8a6a9069bbe2e9cafacf4ff6137f82) ### Suggested Fix Pass an explicit optimisticRecord parameter when calling updateOneRecord from usePersonAvatarUpload. The useUpdateOneRecord hook uses optimisticRecord via nullish coalescing (optimisticRecord ?? computeOptimisticRecordFromInput(...)), so providing it bypasses the strict field validation in computeOptimisticRecordFromInput entirely. The avatarFile value is extracted into a shared variable to avoid duplication between updateOneRecordInput and optimisticRecord. --- *Generated by [Sonarly](https://sonarly.com)* --------- Co-authored-by: Sonarly Claude Code Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Etienne --- .../record-show/hooks/usePersonAvatarUpload.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/record-show/hooks/usePersonAvatarUpload.ts b/packages/twenty-front/src/modules/object-record/record-show/hooks/usePersonAvatarUpload.ts index e39906a3ec..9be5605e39 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/hooks/usePersonAvatarUpload.ts +++ b/packages/twenty-front/src/modules/object-record/record-show/hooks/usePersonAvatarUpload.ts @@ -1,8 +1,8 @@ -import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; +import { useApolloClient } from '@apollo/client'; import { t } from '@lingui/core/macro'; import { assertIsDefinedOrThrow, isDefined } from 'twenty-shared/utils'; import { @@ -14,10 +14,10 @@ import { } from '~/generated-metadata/graphql'; export const usePersonAvatarUpload = (personRecordId: string) => { - const coreClient = useApolloCoreClient(); + const apolloClient = useApolloClient(); const [uploadImage] = useUploadImageMutation(); const [uploadFilesFieldFile] = useUploadFilesFieldFileMutation({ - client: coreClient, + client: apolloClient, }); const { updateOneRecord } = useUpdateOneRecord();