twentyhq/twenty · critical · Error
Failed to add NOT_RECORDED to CallRecording status metadata
Error message
Failed to add NOT_RECORDED to CallRecording status metadata for workspace ${workspaceId}: ${JSON.stringify(validateAndBuildResult, null, 2)} What it means
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.
Source
Thrown at packages/twenty-server/src/database/commands/upgrade-version-command/2-26/2-26-workspace-command-1785334800000-add-not-recorded-call-recording-status.command.ts:155
const validateAndBuildResult =
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunLegacyWorkspaceMigration(
{
isSystemBuild: true,
applicationUniversalIdentifier:
twentyStandardFlatApplication.universalIdentifier,
workspaceId,
allFlatEntityOperationByMetadataName: {
fieldMetadata: {
flatEntityToCreate: [],
flatEntityToDelete: [],
flatEntityToUpdate: [updatedStatusField],
},
},
},
);
if (validateAndBuildResult.status === 'fail') {
throw new Error(
`Failed to add NOT_RECORDED to CallRecording status metadata for workspace ${workspaceId}: ${JSON.stringify(
validateAndBuildResult,
null,
2,
)}`,
);
}
this.logger.log(
`Added NOT_RECORDED to CallRecording status metadata for workspace ${workspaceId}`,
);
}
}
View on GitHub (pinned to 1f5dd2bbd2)
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.
Defensive patterns
Strategy: try-catch
Validate before calling
// Idempotency pre-check the command already does, but harden against id/value drift:
const currentOptions = (selectStatusField.options ?? []);
const hasId = currentOptions.some(o => o.id === NOT_RECORDED_STATUS_OPTION.id);
const hasValue = currentOptions.some(o => o.value === CallRecordingStatus.NOT_RECORDED);
if (hasId || hasValue) { /* reconcile before submitting the update */ } Try / catch
try {
await command.runOnWorkspace({ workspaceId, options });
} catch (e) {
const report = JSON.parse(e.message.split(':').slice(1).join(':').trim());
// report.report.fieldMetadata[] -> [{ universalIdentifier, errorCode }]
logger.error({ workspaceId, report }, '2.26 NOT_RECORDED upgrade failed');
// continue to next workspace rather than aborting the whole upgrade
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- CallRecording status metadata is not a SELECT field for work
- Failed to backfill standard skills for workspace ${workspace
- Failed to add the Block Settings command menu item for works
- Failed to backfill record page(s) for workspace ${workspaceI
- Failed to add the CalendarEvent Call Recording tab for works
AI-assisted analysis of twentyhq/twenty@1f5dd2bbd2 (2026-08-12).
Data as JSON: /api/errors/928d7ce954ee54ae.
Report an issue: GitHub.