{"record":{"id":"928d7ce954ee54ae","repo":"twentyhq/twenty","slug":"failed-to-add-not-recorded-to-callrecording-status","errorCode":null,"errorMessage":"Failed to add NOT_RECORDED to CallRecording status metadata for workspace ${workspaceId}: ${JSON.stringify(validateAndBuildResult, null, 2)}","messagePattern":"Failed to add NOT_RECORDED to CallRecording status metadata 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":155,"sourceCode":"    const validateAndBuildResult =\n      await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration(\n        {\n          isSystemBuild: true,\n          applicationUniversalIdentifier:\n            twentyStandardFlatApplication.universalIdentifier,\n          workspaceId,\n          allFlatEntityOperationByMetadataName: {\n            fieldMetadata: {\n              flatEntityToCreate: [],\n              flatEntityToDelete: [],\n              flatEntityToUpdate: [updatedStatusField],\n            },\n          },\n        },\n      );\n\n    if (validateAndBuildResult.status === 'fail') {\n      throw new Error(\n        `Failed to add NOT_RECORDED to CallRecording status metadata for workspace ${workspaceId}: ${JSON.stringify(\n          validateAndBuildResult,\n          null,\n          2,\n        )}`,\n      );\n    }\n\n    this.logger.log(\n      `Added NOT_RECORDED to CallRecording status metadata for workspace ${workspaceId}`,\n    );\n  }\n}\n","sourceCodeStart":137,"sourceCodeEnd":169,"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#L137-L169","documentation":"Thrown by the same 2.26 command (add-not-recorded-call-recording-status) after it builds the updatedStatusField with the appended NOT_RECORDED option and submits it through validateBuildAndRunLegacyWorkspaceMigration. The orchestrator returned status === 'fail', meaning one or more flat-field validations or the generated SQL migration could not be built/applied. The thrown message embeds the full WorkspaceMigrationOrchestratorFailedResult (status + per-metadata-name report of FailedFlatEntityValidation entries), which names the exact rule and entity that failed.","triggerScenarios":"The NOT_RECORDED option collides (duplicate id/value with an existing option), the computed nextOptionPosition conflicts, the status field's options array fails the select-field validator, or a dependent relation/view referencing the field blocks the metadata update. Also fires if the workspace cache is stale relative to the live metadata and the build detects an inconsistency.","commonSituations":"A workspace that already has a partially-added NOT_RECORDED (id or value present but the early `hasNotRecordedStatus` check missed it due to a value/label mismatch); options with non-unique ids from a prior manual insert; a workspace whose metadata cache was not invalidated after an out-of-band DB edit.","solutions":["Read the JSON report in the thrown message — it lists, per metadata name, each FailedFlatEntityValidation (entity universalIdentifier + error code).","If the report shows a duplicate-option/id conflict, remove the stray option row for that field in the workspace metadata so the append is clean.","Force a cache recompute for the workspace (the command uses workspaceCacheService.getOrRecompute; invalidate and re-run) so the build sees consistent state.","Re-run the single 2.26 command for the workspace once the conflict is cleared."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Idempotency pre-check the command already does, but harden against id/value drift:\nconst currentOptions = (selectStatusField.options ?? []);\nconst hasId = currentOptions.some(o => o.id === NOT_RECORDED_STATUS_OPTION.id);\nconst hasValue = currentOptions.some(o => o.value === CallRecordingStatus.NOT_RECORDED);\nif (hasId || hasValue) { /* reconcile before submitting the update */ }","typeGuard":null,"tryCatchPattern":"try {\n  await command.runOnWorkspace({ workspaceId, options });\n} catch (e) {\n  const report = JSON.parse(e.message.split(':').slice(1).join(':').trim());\n  // report.report.fieldMetadata[] -> [{ universalIdentifier, errorCode }]\n  logger.error({ workspaceId, report }, '2.26 NOT_RECORDED upgrade failed');\n  // continue to next workspace rather than aborting the whole upgrade\n}","preventionTips":["Inspect the embedded orchestrator report first — it names the exact failing validation.","Invalidate and recompute the workspace field-metadata cache before retrying so the build sees consistent state.","Ensure no option id/value duplicates exist on the status field before upgrading."],"tags":["migration","upgrade-command","validate-and-build","workspace","select-field","call-recording","orchestrator"],"backgroundTag":null,"analyzedSha":"1f5dd2bbd2a8da3419c8cfd52dd545c0024df1a6","analyzedAt":"2026-08-12T15:37:27.593Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}