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

  1. Query core.fieldMetadata for the CallRecording status field (universal identifier CALL_RECORDING_STATUS_FIELD_UNIVERSAL_IDENTIFIER) and inspect its type.
  2. If it was changed erroneously, restore type to SELECT with the expected options payload, then re-run.
  3. If the workspace legitimately has no status field, confirm the isDefined branch above is being hit (it should skip, not throw).
  4. 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

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


AI-assisted analysis of twentyhq/twenty@1f5dd2bbd2 (2026-08-12). Data as JSON: /api/errors/882543670a7759e5. Report an issue: GitHub.