{"record":{"id":"683d9bf30c4cc80e","repo":"phacility/phabricator","slug":"no-private-key-exists-at-path-s","errorCode":null,"errorMessage":"No private key exists at path \"%s\"!","messagePattern":"No private key exists at path \"(.+?)\"!","errorType":"console","errorClass":"PhutilArgumentUsageException","httpStatus":null,"severity":"error","filePath":"src/applications/almanac/management/AlmanacManagementRegisterWorkflow.php","lineNumber":79,"sourceCode":"\n    $identity_device = id(new AlmanacDeviceQuery())\n      ->setViewer($viewer)\n      ->withNames(array($raw_device))\n      ->executeOne();\n    if (!$identity_device) {\n      throw new PhutilArgumentUsageException(\n        pht(\n          'No such device \"%s\" exists!', $raw_device));\n    }\n\n    $private_key_path = $args->getArg('private-key');\n    if (!strlen($private_key_path)) {\n      throw new PhutilArgumentUsageException(\n        pht('Specify a private key with --private-key.'));\n    }\n\n    if (!Filesystem::pathExists($private_key_path)) {\n      throw new PhutilArgumentUsageException(\n        pht('No private key exists at path \"%s\"!', $private_key_path));\n    }\n\n    $raw_private_key = Filesystem::readFile($private_key_path);\n\n    $phd_user = PhabricatorEnv::getEnvConfig('phd.user');\n    if (!$phd_user) {\n      throw new PhutilArgumentUsageException(\n        pht(\n          'Config option \"phd.user\" is not set. You must set this option '.\n          'so the private key can be stored with the correct permissions.'));\n    }\n\n    $tmp = new TempFile();\n    list($err) = exec_manual('chown %s %s', $phd_user, $tmp);\n    if ($err) {\n      throw new PhutilArgumentUsageException(\n        pht(","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/almanac/management/AlmanacManagementRegisterWorkflow.php#L61-L97","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the path character by character and use an absolute path for --private-key.","If generating the key in automation, add an explicit existence check (and chmod 600) between generation and register.","Confirm mounts/permissions when running under sudo or inside containers."],"exampleFix":"# before\n$ bin/almanac register --device web-001 --private-key ./device.key\nUsage Exception: No private key exists at path \"./device.key\"!\n\n# after\n$ ls -l /root/.ssh/device.key\n$ bin/almanac register --device web-001 --private-key /root/.ssh/device.key","handlingStrategy":"validation","validationCode":"$key = '/root/.ssh/device.key'; // always absolute\nif (!file_exists($key)) {\n  throw new RuntimeException(\"Private key not found at '{$key}'\");\n}\n// invoke: bin/almanac register --device X --private-key $key","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use absolute paths for --private-key, especially under sudo/cron/containers.","Order automation: generate key -> verify exists -> register.","Fail provisioning loudly when the key artifact is absent instead of letting the CLI discover it."],"tags":["phabricator","almanac","cli","file-not-found","ssh-key"],"backgroundTag":"file-not-found","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}