twentyhq/twenty · error · Error

Failed to sync CallRecording status metadata for workspace $

Error message

Failed to sync CallRecording status metadata for workspace ${workspaceId}: ${JSON.stringify(validateAndBuildResult, null, 2)}

What it means

Thrown by the 2.16 sync-call-recording-status command after it builds updatedStatusField (rewriting LEGACY_FAILED_STATUS to FAILED_STATUS in the SELECT options) and validateBuildAndRunLegacyWorkspaceMigration returns status 'fail'. The full validateAndBuildResult is JSON-stringified into the message. The status field has already passed the SELECT type check (error 125), so this failure is in the build of the update payload.

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:141

    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 sync CallRecording status metadata for workspace ${workspaceId}: ${JSON.stringify(
          validateAndBuildResult,
          null,
          2,
        )}`,
      );
    }

    this.logger.log(
      `Synced CallRecording status metadata from ${LEGACY_FAILED_STATUS} to ${FAILED_STATUS} for workspace ${workspaceId}`,
    );
  }
}

View on GitHub (pinned to 1f5dd2bbd2)

Solutions

  1. Read the JSON payload in the error message to find the failing option and error code.
  2. Dedupe or repair the status field's options in core.fieldMetadata so the rewritten payload validates.
  3. Ensure no other upgrade or metadata-edit process is touching the CallRecording status field concurrently.
  4. Re-run the workspace upgrade.
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the status options array does not already contain FAILED_STATUS
// (which would collide with the rewrite from LEGACY_FAILED_STATUS).
const opts = await dataSource.query(`
  SELECT "options" FROM core."fieldMetadata"
  WHERE "nameSingular" = 'status'
    AND "objectMetadataId" = (SELECT id FROM core."objectMetadata" WHERE "nameSingular" = 'callRecording')
`);
const hasFailed = opts[0]?.options?.some((o: any) => o.value === FAILED_STATUS);
const hasLegacy = opts[0]?.options?.some((o: any) => o.value === LEGACY_FAILED_STATUS);
if (hasFailed && hasLegacy) throw new Error('Both FAILED and LEGACY_FAILED present; dedupe first');

Type guard

function isFailResult(r: unknown): r is { status: 'fail' } {
  return typeof r === 'object' && r !== null && (r as any).status === 'fail';
}

Try / catch

try {
  const res = await service.validateBuildAndRunLegacyWorkspaceMigration(payload);
  if (res.status === 'fail') throw new Error(`...${JSON.stringify(res, null, 2)}`);
} catch (err) { upgradeAudit.record(workspaceId, command.id, err); throw err; }

Prevention

When it happens

Trigger: Running the 2.16 upgrade where the updated options payload violates validation (duplicate option values, missing required option fields, or the fieldMetadata row is locked by an active concurrent migration).

Common situations: Workspace whose status field already contains FAILED_STATUS alongside LEGACY_FAILED_STATUS (duplicate after rewrite); options array missing id/name required keys; concurrent upgrade runs.

Related errors


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