{"record":{"id":"3eeaf6060ff2434e","repo":"phacility/phabricator","slug":"specify-a-private-key-with-private-key","errorCode":null,"errorMessage":"Specify a private key with --private-key.","messagePattern":"Specify a private key with --private-key\\.","errorType":"console","errorClass":"PhutilArgumentUsageException","httpStatus":null,"severity":"warning","filePath":"src/applications/almanac/management/AlmanacManagementRegisterWorkflow.php","lineNumber":74,"sourceCode":"\n    $raw_device = $device_name;\n    if (strlen($identify_as)) {\n      $raw_device = $identify_as;\n    }\n\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","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/almanac/management/AlmanacManagementRegisterWorkflow.php#L56-L92","documentation":"Usage exception from `bin/almanac register`: the --private-key flag is missing or empty. The workflow derives the corresponding public key on the fly with `ssh-keygen -y -f <tmp-copy>` and matches it against trusted device keys, so the private key file is required input for registration.","triggerScenarios":"Running bin/almanac register --device web-001 without --private-key; an automation script passing an unexpanded variable like --private-key $KEY_PATH with KEY_PATH unset; using --key or --private_key flag names that do not exist.","commonSituations":"Provisioning scripts that generate the keypair at runtime but reference the path before generation completes; interactive use from memory; flag renamed/typo'd in copy-pasted runbooks.","solutions":["Generate (or locate) the device private key and pass it: bin/almanac register --device X --private-key /path/to/id_rsa.","In scripts, verify the key path variable is set and non-empty before invoking the CLI.","Ensure the daemon/CLI user can read the key file; ssh-keygen refuses world-readable keys (the workflow copies it to a 0600 temp file, but the source must be readable)."],"exampleFix":"# before\n$ bin/almanac register --device web-001\nUsage Exception: Specify a private key with --private-key.\n\n# after\n$ ssh-keygen -t ed25519 -f /root/device.key -N ''\n$ bin/almanac register --device web-001 --private-key /root/device.key","handlingStrategy":"validation","validationCode":": \"${DEVICE_KEY_PATH:?device private key path required}\"\n[ -s \"$DEVICE_KEY_PATH\" ] || { echo \"key missing: $DEVICE_KEY_PATH\" >&2; exit 1; }\nbin/almanac register --device \"$ALMANAC_DEVICE\" --private-key \"$DEVICE_KEY_PATH\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Generate the keypair in the same script step that registers, so the path is always populated.","Store key paths in one config var and reference it everywhere.","Check `bin/almanac register --help` when in doubt about flag names."],"tags":["phabricator","almanac","cli","usage-error","ssh-key","register"],"backgroundTag":"missing-cli-argument","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}