phacility/phabricator · error · PhabricatorApplicationTransactionValidationException

The chosen callsign or repository short name is already in u

Error message

The chosen callsign or repository short name is already in use by another repository.

What it means

Thrown by PhabricatorRepositoryEditor::didCatchDuplicateKeyException() when saving or editing a repository triggers a database duplicate-key exception on a unique index. In Phabricator, both the repository callsign (e.g. ABC) and the repository short name (e.g. myrepo used in diffusion URLs) are globally unique. The raw Lisk duplicate-key error is converted into a PhabricatorApplicationTransactionValidationException so the UI can show a field-level validation message.

Source

Thrown at src/applications/repository/editor/PhabricatorRepositoryEditor.php:39

    return $types;
  }

  protected function didCatchDuplicateKeyException(
    PhabricatorLiskDAO $object,
    array $xactions,
    Exception $ex) {

    $errors = array();

    $errors[] = new PhabricatorApplicationTransactionValidationError(
      null,
      pht('Invalid'),
      pht(
        'The chosen callsign or repository short name is already in '.
        'use by another repository.'),
      null);

    throw new PhabricatorApplicationTransactionValidationException($errors);
  }

  protected function supportsSearch() {
    return true;
  }

  protected function applyFinalEffects(
    PhabricatorLiskDAO $object,
    array $xactions) {

    // If the repository does not have a local path yet, assign it one based
    // on its ID. We can't do this earlier because we won't have an ID yet.
    $local_path = $object->getLocalPath();
    if ($local_path === null || !strlen($local_path)) {
      $local_key = 'repository.default-local-path';

      $local_root = PhabricatorEnv::getEnvConfig($local_key);
      $local_root = rtrim($local_root, '/');

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Pick a different callsign or short name for the repository
  2. Find the conflicting repository: browse /diffusion/ or query diffusion.repository.search via Conduit, then rename or delete it if it is an accidental duplicate
  3. If writing a migration script, check for an existing repository by callsign and short name before creating
  4. Retry the create or edit after the collision is resolved

Example fix

// before
id(new PhabricatorRepository())
  ->setCallsign('ABC')
  ->setName('widgets')
  ->save(); // throws: 'ABC' already in use

// after
$existing = id(new PhabricatorRepositoryQuery())
  ->setViewer($viewer)
  ->withCallsigns(array('ABC'))
  ->executeOne();
if ($existing) {
  $repository = $existing; // reuse instead of colliding
} else {
  $repository = id(new PhabricatorRepository())
    ->setCallsign('ABC')
    ->setName('widgets')
    ->save();
}
Defensive patterns

Strategy: validation

Validate before calling

// Before create/edit, check uniqueness the way the editor does:
$existing = id(new PhabricatorRepositoryQuery())
  ->setViewer($viewer)
  ->withCallsigns(array($callsign))
  ->executeOne();
if ($existing) {
  // pick another callsign or reuse this repository
}

Try / catch

try {
  id(new PhabricatorRepositoryEditor())
    ->setActor($viewer)
    ->setContentSource($source)
    ->applyTransactions($repository, $xactions);
} catch (PhabricatorApplicationTransactionValidationException $ex) {
  foreach ($ex->getErrors() as $error) {
    // map the 'Invalid' message back to the callsign / short-name fields
  }
}

Prevention

When it happens

Trigger: Creating or editing a repository via Diffusion UI, Conduit (repository.create / repository.edit), or CLI where the chosen callsign or short name collides with an existing repository row; the catch wraps the INSERT/UPDATE inside applyTransactions. Also triggered by re-importing a repository that already exists under another name, or by two concurrent creates picking the same callsign.

Common situations: Creating a repo with a callsign already used by another (possibly dormant) repository; renaming a repo to a short name another repo occupies; migration or import scripts that assume the target name is free; case-sensitivity surprises such as Repo vs repo depending on DB collation.

Related errors


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/519f47ae144610fb. Report an issue: GitHub.