{"record":{"id":"26143095f8bd8556","repo":"twentyhq/twenty","slug":"callrecording-status-metadata-is-not-a-select-fiel-261430","errorCode":null,"errorMessage":"CallRecording status metadata is not a SELECT field for workspace ${workspaceId}","messagePattern":"CallRecording status metadata is not a SELECT field for workspace (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"packages/twenty-server/src/database/commands/upgrade-version-command/2-26/2-26-workspace-command-1785334800000-add-not-recorded-call-recording-status.command.ts","lineNumber":89,"sourceCode":"\n      return;\n    }\n\n    const statusField =\n      flatFieldMetadataMaps.byUniversalIdentifier[\n        CALL_RECORDING_STATUS_FIELD_UNIVERSAL_IDENTIFIER\n      ];\n\n    if (!isDefined(statusField)) {\n      this.logger.log(\n        `CallRecording status field metadata does not exist for workspace ${workspaceId}, skipping`,\n      );\n\n      return;\n    }\n\n    if (statusField.type !== FieldMetadataType.SELECT) {\n      throw new Error(\n        `CallRecording status metadata is not a SELECT field for workspace ${workspaceId}`,\n      );\n    }\n\n    const selectStatusField =\n      statusField as FlatFieldMetadata<FieldMetadataType.SELECT>;\n    const currentOptions = selectStatusField.options ?? [];\n    const hasNotRecordedStatus = currentOptions.some(\n      (option) => option.value === CallRecordingStatus.NOT_RECORDED,\n    );\n\n    if (hasNotRecordedStatus) {\n      this.logger.log(\n        `CallRecording status metadata already has NOT_RECORDED for workspace ${workspaceId}, skipping`,\n      );\n\n      return;\n    }","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/twentyhq/twenty/blob/1f5dd2bbd2a8da3419c8cfd52dd545c0024df1a6/packages/twenty-server/src/database/commands/upgrade-version-command/2-26/2-26-workspace-command-1785334800000-add-not-recorded-call-recording-status.command.ts#L71-L107","documentation":"Thrown by the 2.26 workspace upgrade command that adds the NOT_RECORDED option to the CallRecording.status select field. After confirming the CallRecording object and its status field both exist, it asserts statusField.type === FieldMetadataType.SELECT before casting and appending an option. The throw signals that the workspace's status field metadata has drifted from the standard definition (which declares it as SELECT) — almost always manual edits, a half-applied earlier migration, or a custom override.","triggerScenarios":"The command runs per-workspace during the 2.26.0 upgrade. It loads statusField from flatFieldMetadataMaps by CALL_RECORDING_STATUS_FIELD_UNIVERSAL_IDENTIFIER, and the stored type is anything other than SELECT (e.g. it was changed to a multi-select / text / relation, or the column was repurposed). It also fires if the field was re-created with a different type after a botched prior upgrade.","commonSituations":"A workspace where an admin or a prior custom migration changed the CallRecording.status field type; schema drift between the core metadata tables and the standard definition; an interrupted 2.26 run that left the field half-modified; imports from another CRM that overwrote the status column type.","solutions":["Query the workspace metadata: SELECT type FROM core.fieldMetadata WHERE universalIdentifier = '<callRecording.status UI>' for the failing workspaceId to see the actual stored type.","If the field was manually repurposed, restore it to type = 'SELECT' (or rename/drop the custom field and let the standard one be re-seeded) before re-running the upgrade.","Re-run the command for just that workspace: npx nx run twenty-server:database:migrate:prod scoped to the 2.26 command.","If the field genuinely should not be SELECT in this workspace, mark the workspace upgrade as handled and skip — but verify no downstream code depends on status being a select."],"exampleFix":"// before — stored metadata has type drift\n// statusField.type === 'TEXT'  -> throws\n\n// fix in DB (restore standard type), then the command proceeds:\n//   UPDATE core.fieldMetadata SET type = 'SELECT'\n//   WHERE \"universalIdentifier\" =\n//     STANDARD_OBJECTS.callRecording.fields.status.universalIdentifier;\n// then re-run the 2.26 workspace command.","handlingStrategy":"validation","validationCode":"// Before running the 2.26 upgrade for a workspace, verify the status field type:\nconst statusField = flatFieldMetadataMaps.byUniversalIdentifier[\n  CALL_RECORDING_STATUS_FIELD_UNIVERSAL_IDENTIFIER,\n];\nif (isDefined(statusField) && statusField.type !== FieldMetadataType.SELECT) {\n  // repair or skip this workspace before invoking the command\n}","typeGuard":"import { FieldMetadataType } from 'twenty-shared/types';\n\nconst isSelectField = (\n  field: { type: FieldMetadataType } | undefined,\n): field is { type: FieldMetadataType.SELECT; options?: unknown[] } =>\n  field?.type === FieldMetadataType.SELECT;","tryCatchPattern":null,"preventionTips":["Do not manually change standard field types; if a field must be repurposed, create a custom field instead.","Run upgrades on a DB backup so a drifted standard field can be restored.","Before upgrading, diff workspace standard field types against the standard definition for the affected objects."],"tags":["migration","upgrade-command","workspace","select-field","metadata-drift","call-recording"],"backgroundTag":null,"analyzedSha":"1f5dd2bbd2a8da3419c8cfd52dd545c0024df1a6","analyzedAt":"2026-08-12T15:37:27.593Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}