twentyhq/twenty · error · Error
CallRecording status metadata is not a SELECT field for work
Error message
CallRecording status metadata is not a SELECT field for workspace ${workspaceId} What it means
Thrown by the 2.16 sync-call-recording-status command when the CallRecording status field exists but its type is not FieldMetadataType.SELECT. The command's whole purpose is to rewrite the SELECT option value LEGACY_FAILED_STATUS to FAILED_STATUS, so a non-SELECT type makes the rewrite impossible. The status field is located by universal identifier; a missing field is a graceful skip, but a wrong-typed field is a hard error.
Source
Thrown at packages/twenty-server/src/database/commands/upgrade-version-command/2-16/2-16-workspace-command-1799100001000-sync-call-recording-status.command.ts:78
return;
}
const statusField =
flatFieldMetadataMaps.byUniversalIdentifier[
CALL_RECORDING_STATUS_FIELD_UNIVERSAL_IDENTIFIER
];
if (!isDefined(statusField)) {
this.logger.log(
`CallRecording status field metadata does not exist for workspace ${workspaceId}, skipping`,
);
return;
}
if (statusField.type !== FieldMetadataType.SELECT) {
throw new Error(
`CallRecording status metadata is not a SELECT field for workspace ${workspaceId}`,
);
}
const selectStatusField =
statusField as FlatFieldMetadata<FieldMetadataType.SELECT>;
const optionsWithFailedStatus = (selectStatusField.options ?? []).map(
(option) =>
option.value === LEGACY_FAILED_STATUS
? { ...option, value: FAILED_STATUS }
: option,
);
const hasLegacyFailedStatus = optionsWithFailedStatus.some(
(option, index) =>
option.value !== selectStatusField.options?.[index]?.value,
);
if (!hasLegacyFailedStatus) {View on GitHub (pinned to 1f5dd2bbd2)
Solutions
- Query core.fieldMetadata for the CallRecording status field (universal identifier CALL_RECORDING_STATUS_FIELD_UNIVERSAL_IDENTIFIER) and inspect its type.
- If it was changed erroneously, restore type to SELECT with the expected options payload, then re-run.
- If the workspace legitimately has no status field, confirm the isDefined branch above is being hit (it should skip, not throw).
- After correcting the type, re-run the 2.16 upgrade for the workspace.
Example fix
-- before
core.fieldMetadata: { universalIdentifier: 'status', type: 'TEXT' }
-- after
UPDATE core."fieldMetadata" SET "type" = 'SELECT' WHERE "nameSingular" = 'status' AND "objectMetadataId" = (SELECT id FROM core."objectMetadata" WHERE "nameSingular" = 'callRecording'); Defensive patterns
Strategy: type-guard
Validate before calling
// Before the upgrade, confirm the CallRecording status field is SELECT if present.
const row = await dataSource.query(`
SELECT "type" FROM core."fieldMetadata"
WHERE "nameSingular" = 'status'
AND "objectMetadataId" = (SELECT id FROM core."objectMetadata" WHERE "nameSingular" = 'callRecording')
`);
if (row.length && row[0].type !== 'SELECT') {
throw new Error(`CallRecording status field type is ${row[0].type}, expected SELECT`);
} Type guard
import { FieldMetadataType } from '@twenty/shared';
function isSelectField(field: { type: FieldMetadataType } | undefined | null): field is { type: FieldMetadataType.SELECT } {
return isDefined(field) && field.type === FieldMetadataType.SELECT;
} Try / catch
if (!isSelectField(statusField)) {
throw new Error(`CallRecording status metadata is not a SELECT field for workspace ${workspaceId}`);
} Prevention
- Never change a standard SELECT field's type manually in the DB.
- Detect and report type drift on standard fields before upgrade via a preflight check.
- Keep custom fields from reusing standard universal identifiers.
When it happens
Trigger: Workspace whose CallRecording status fieldMetadata row has type other than SELECT (e.g. mutated to TEXT, or a custom field shadows the standard one). Triggered during the 2.16 upgrade when statusField.type !== SELECT after the isDefined check passes.
Common situations: Manual edit of the status field's type in the DB; a prior migration that changed the field type; conflicting custom field sharing the universal identifier.
Related errors
- Failed to sync CallRecording status metadata for workspace $
- Failed to rename CallRecording name collision for workspace
- Failed to create CallRecording standard objects for workspac
- Failed to create CallRecording recordingRequestStatus metada
- Failed to sync CallRecording navigation command menu item av
AI-assisted analysis of twentyhq/twenty@1f5dd2bbd2 (2026-08-12).
Data as JSON: /api/errors/882543670a7759e5.
Report an issue: GitHub.