{"record":{"id":"41117803d6547af3","repo":"twentyhq/twenty","slug":"could-not-find-an-available-callrecordingold-name","errorCode":null,"errorMessage":"Could not find an available callRecordingOld name after ${MAX_OLD_NAME_ATTEMPTS} attempts","messagePattern":"Could not find an available callRecordingOld name after (.+?) attempts","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/twenty-server/src/database/commands/upgrade-version-command/2-10/utils/call-recording-name-collision.util.ts","lineNumber":83,"sourceCode":"\n  for (let attempt = 0; attempt < MAX_OLD_NAME_ATTEMPTS; attempt++) {\n    const discriminator = attempt === 0 ? '' : `${attempt + 1}`;\n    const nameSingular = `${CALL_RECORDING_OLD_NAME_SINGULAR}${discriminator}`;\n    const namePlural = `${CALL_RECORDING_OLD_NAME_PLURAL}${discriminator}`;\n\n    if (!takenNames.has(nameSingular) && !takenNames.has(namePlural)) {\n      const labelSuffix = discriminator === '' ? '' : ` ${discriminator}`;\n\n      return {\n        nameSingular,\n        namePlural,\n        labelSingular: `Call Recording (Old)${labelSuffix}`,\n        labelPlural: `Call Recordings (Old)${labelSuffix}`,\n      };\n    }\n  }\n\n  throw new Error(\n    `Could not find an available callRecordingOld name after ${MAX_OLD_NAME_ATTEMPTS} attempts`,\n  );\n};\n\nexport const buildCallRecordingObjectRenameUpdates = ({\n  flatObjectMetadataMaps,\n  now,\n}: {\n  flatObjectMetadataMaps: FlatEntityMaps<FlatObjectMetadata>;\n  now: string;\n}): FlatObjectMetadata[] => {\n  const reservedOldNames = new Set<string>();\n\n  return findCallRecordingObjectNameCollisions(flatObjectMetadataMaps).map(\n    (collidingObjectMetadata) => {\n      const { nameSingular, namePlural, labelSingular, labelPlural } =\n        resolveAvailableOldCallRecordingObjectNames(\n          flatObjectMetadataMaps,","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/twentyhq/twenty/blob/1f5dd2bbd2a8da3419c8cfd52dd545c0024df1a6/packages/twenty-server/src/database/commands/upgrade-version-command/2-10/utils/call-recording-name-collision.util.ts#L65-L101","documentation":"Thrown by resolveAvailableOldCallRecordingObjectNames after trying 100 candidate names (callRecordingOld, callRecordingOld2 ... callRecordingOld101) and finding every singular/plural pair already taken in the workspace's object metadata plus the additional reserved set. MAX_OLD_NAME_ATTEMPTS is 100.","triggerScenarios":"A workspace has 100+ existing objects whose nameSingular/namePlural cover the entire callRecordingOld<number> range, so no free slot remains for renaming a colliding callRecording object.","commonSituations":"Extremely rare: requires deliberate or pathological creation of 100+ objects with those exact names; re-running the migration many times against an already-collision-heavy workspace; a corrupted workspace with mass duplicate objects.","solutions":["Query the workspace for objects whose name matches /^callRecording(Old|sOld)\\d*$/ and manually rename or delete the surplus.","Re-run the command after freeing names; collision resolution will then find a slot.","If genuinely needed, raise MAX_OLD_NAME_ATTEMPTS in the util and re-run (last resort)."],"exampleFix":"// before: relies on 100 attempts silently throwing\nconst names = resolveAvailableOldCallRecordingObjectNames(maps, reserved);\n\n// after: pre-check capacity and surface a clear signal\nconst freeCapacity = 100 - countNamesMatching(maps, /^callRecording(Old|sOld)\\d*$/);\nif (freeCapacity <= 0) {\n  throw new Error('No free callRecordingOld slots; clean up duplicate objects first');\n}","handlingStrategy":"validation","validationCode":"import { resolveAvailableOldCallRecordingObjectNames } from '../utils/call-recording-name-collision.util';\n\n// Before calling, count existing callRecordingOld* names to ensure a slot will be found:\nconst takenCount = Object.values(flatObjectMetadataMaps.byUniversalIdentifier)\n  .filter(isDefined)\n  .filter((o) => /^callRecording(Old|sOld)\\d*$/.test(o.nameSingular) || /^callRecording(s)?Old\\d*$/.test(o.namePlural))\n  .length;\nif (takenCount >= 100) {\n  throw new Error('callRecordingOld namespace exhausted; remove duplicate objects before retrying');\n}\nconst names = resolveAvailableOldCallRecordingObjectNames(flatObjectMetadataMaps, reservedOldNames);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Before running the CallRecording sync, query for objects matching /^callRecording(Old|sOld)\\d*$/ and clean up duplicates.","Recompute the workspace cache so the taken-name set reflects reality.","Treat this error as a data-hygiene signal, not a transient failure."],"tags":["migration","call-recording","name-collision","rename","exhaustion"],"backgroundTag":null,"analyzedSha":"1f5dd2bbd2a8da3419c8cfd52dd545c0024df1a6","analyzedAt":"2026-08-12T15:37:27.593Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}