phacility/phabricator · error · PhutilArgumentUsageException

No private key exists at path "%s"!

Error message

No private key exists at path "%s"!

What it means

Usage exception from `bin/almanac register`: --private-key was provided but no file exists at that path (Filesystem::pathExists check). The path is then handed to Filesystem::readFile, so the workflow fails fast with a readable message instead of a raw I/O error.

Source

Thrown at src/applications/almanac/management/AlmanacManagementRegisterWorkflow.php:79

    $identity_device = id(new AlmanacDeviceQuery())
      ->setViewer($viewer)
      ->withNames(array($raw_device))
      ->executeOne();
    if (!$identity_device) {
      throw new PhutilArgumentUsageException(
        pht(
          'No such device "%s" exists!', $raw_device));
    }

    $private_key_path = $args->getArg('private-key');
    if (!strlen($private_key_path)) {
      throw new PhutilArgumentUsageException(
        pht('Specify a private key with --private-key.'));
    }

    if (!Filesystem::pathExists($private_key_path)) {
      throw new PhutilArgumentUsageException(
        pht('No private key exists at path "%s"!', $private_key_path));
    }

    $raw_private_key = Filesystem::readFile($private_key_path);

    $phd_user = PhabricatorEnv::getEnvConfig('phd.user');
    if (!$phd_user) {
      throw new PhutilArgumentUsageException(
        pht(
          'Config option "phd.user" is not set. You must set this option '.
          'so the private key can be stored with the correct permissions.'));
    }

    $tmp = new TempFile();
    list($err) = exec_manual('chown %s %s', $phd_user, $tmp);
    if ($err) {
      throw new PhutilArgumentUsageException(
        pht(

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Check the path character by character and use an absolute path for --private-key.
  2. If generating the key in automation, add an explicit existence check (and chmod 600) between generation and register.
  3. Confirm mounts/permissions when running under sudo or inside containers.

Example fix

# before
$ bin/almanac register --device web-001 --private-key ./device.key
Usage Exception: No private key exists at path "./device.key"!

# after
$ ls -l /root/.ssh/device.key
$ bin/almanac register --device web-001 --private-key /root/.ssh/device.key
Defensive patterns

Strategy: validation

Validate before calling

$key = '/root/.ssh/device.key'; // always absolute
if (!file_exists($key)) {
  throw new RuntimeException("Private key not found at '{$key}'");
}
// invoke: bin/almanac register --device X --private-key $key

Prevention

When it happens

Trigger: Typo'd path, e.g. /root/id_deivce; relative path evaluated from a different working directory than expected; key on a volume not mounted in the provisioning environment; script step ordering where register runs before the key is written.

Common situations: Relative paths in cron/daemon contexts where cwd is not the shell's cwd; keys generated as another user with a home path that differs under sudo; race conditions in infrastructure automation.

Related errors


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