phacility/phabricator · error · Exception
Analyzing or decrypting SSH keys requires the "ssh-keygen" b
Error message
Analyzing or decrypting SSH keys requires the "ssh-keygen" binary, but it is not available in "$PATH". Make it available to work with SSH private keys.
What it means
PhabricatorAuthSSHPrivateKey::newBarePrivateKey() analyzes and decrypts SSH private keys by shelling out to ssh-keygen, so its first act is Filesystem::binaryExists('ssh-keygen'). If the binary is not on PATH for the PHP process, it throws before touching the key. This surfaces wherever Phabricator must open a private key: credential testing, repository cloning with SSH key auth, etc.
Source
Thrown at src/applications/auth/sshkey/PhabricatorAuthSSHPrivateKey.php:38
public function getPassphrase() {
return $this->passphrase;
}
public static function newFromRawKey(PhutilOpaqueEnvelope $entire_key) {
$key = new self();
$key->body = $entire_key;
return $key;
}
public function getKeyBody() {
return $this->body;
}
public function newBarePrivateKey() {
if (!Filesystem::binaryExists('ssh-keygen')) {
throw new Exception(
pht(
'Analyzing or decrypting SSH keys requires the "ssh-keygen" binary, '.
'but it is not available in "$PATH". Make it available to work with '.
'SSH private keys.'));
}
$old_body = $this->body;
// Some versions of "ssh-keygen" are sensitive to trailing whitespace for
// some keys. Trim any trailing whitespace and replace it with a single
// newline.
$raw_body = $old_body->openEnvelope();
$raw_body = rtrim($raw_body)."\n";
$old_body = new PhutilOpaqueEnvelope($raw_body);
$tmp = $this->newTemporaryPrivateKeyFile($old_body);
// See T13454 for discussion of why this is so awkward. In broad strokes,View on GitHub (pinned to 5720a38cfe)
Solutions
- Install the OpenSSH client: 'apt-get install openssh-client' (Debian/Ubuntu) or 'yum install openssh-clients' (RHEL/CentOS)
- Verify as the exact user running PHP/daemons: 'which ssh-keygen' must return a path
- Restart web server and phd daemons after installing or changing PATH so they pick up the new environment
Example fix
# before $ sudo -u www-data which ssh-keygen (no output) # after $ sudo apt-get install -y openssh-client $ sudo -u www-data which ssh-keygen /usr/bin/ssh-keygen
Defensive patterns
Strategy: validation
Validate before calling
// Cheap pre-flight before any private-key operation:
if (!Filesystem::binaryExists('ssh-keygen')) {
// Fail with an actionable setup message instead of letting
// newBarePrivateKey() throw mid-operation.
throw new Exception(pht(
'Install openssh-client on this host before testing SSH key credentials.'));
} Try / catch
try {
$bare_key = $private_key->newBarePrivateKey();
} catch (Exception $ex) {
// ssh-keygen missing from PATH: report host setup problem,
// not a key problem.
$diagnostic = pht('Host lacks ssh-keygen; install openssh-client.');
} Prevention
- Bake openssh-client into every container/image that runs Phabricator web or phd daemons
- Verify 'which ssh-keygen' as the www-data/daemon user after deploys or PATH changes
- Add a ssh-keygen availability check to install/upgrade smoke tests
When it happens
Trigger: Calling newBarePrivateKey() (directly or via credential test / Diffusion SSH auth) on a host without openssh-client installed, or where the web-server/daemon user's PATH does not include the directory containing ssh-keygen.
Common situations: Minimal Docker/CI containers that never installed openssh-client; phd daemons restarted with a sanitized PATH after a deploy; macOS or packaged PHP environments with a restricted default PATH.
Related errors
- Failed to convert public key into PKCS8 format. If you are d
- %s subprocess exited before emitting a protocol frame.
- Can not generate keys: unable to find "%s" in PATH!
- No `%s` or `%s` binary was found in %s. You must install Nod
- This public key is already associated with another user or d
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/875e6370e5b88b96.
Report an issue: GitHub.