phacility/phabricator · error · PhutilProxyException

Failed to convert public key into PKCS8 format. If you are d

Error message

Failed to convert public key into PKCS8 format. If you are developing on OSX, you may be able to use `%s` to work around this issue. %s

What it means

PhabricatorAuthSSHPublicKey::getPKCS8Key() first tries the cache, then writes the key to a TempFile and runs 'ssh-keygen -e -m PKCS8 -f <tmp>' to re-encode it. If execx() raises a CommandException, it is wrapped in a PhutilProxyException whose message suggests 'bin/auth cache-pkcs8' as an OSX workaround and embeds the underlying ssh-keygen error.

Source

Thrown at src/applications/auth/sshkey/PhabricatorAuthSSHPublicKey.php:129

  public function toPKCS8() {
    $entire_key = $this->getEntireKey();
    $cache_key = $this->getPKCS8CacheKey($entire_key);

    $cache = PhabricatorCaches::getImmutableCache();
    $pkcs8_key = $cache->getKey($cache_key);
    if ($pkcs8_key) {
      return $pkcs8_key;
    }

    $tmp = new TempFile();
    Filesystem::writeFile($tmp, $this->getEntireKey());
    try {
      list($pkcs8_key) = execx(
        'ssh-keygen -e -m PKCS8 -f %s',
        $tmp);
    } catch (CommandException $ex) {
      unset($tmp);
      throw new PhutilProxyException(
        pht(
          'Failed to convert public key into PKCS8 format. If you are '.
          'developing on OSX, you may be able to use `%s` '.
          'to work around this issue. %s',
          'bin/auth cache-pkcs8',
          $ex->getMessage()),
        $ex);
    }
    unset($tmp);

    $cache->setKey($cache_key, $pkcs8_key);

    return $pkcs8_key;
  }

  public function forcePopulatePKCS8Cache($pkcs8_key) {
    $entire_key = $this->getEntireKey();
    $cache_key = $this->getPKCS8CacheKey($entire_key);

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Run the documented workaround: './bin/auth cache-pkcs8' to precompute and store PKCS8 key bodies in the cache
  2. Install a real OpenSSH build earlier in PATH (e.g. brew install openssh on macOS) so system ssh-keygen honors '-m PKCS8'
  3. Inspect the chained CommandException message (getPrevious()) for the exact ssh-keygen stderr to confirm the cause

Example fix

# before
$ echo test | ssh-keygen -e -m PKCS8 -f /dev/stdin   # wrong/copy output on OSX ssh-keygen

# after
$ brew install openssh
$ /usr/local/opt/openssh/bin/ssh-keygen -e -m PKCS8 -f ./id_ed25519.pub  # valid PKCS8
$ ./bin/auth cache-pkcs8
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-warm the cache so runtime conversion never needs ssh-keygen:
// run once during deploy on a host with a known-good ssh-keygen:
//   ./bin/auth cache-pkcs8
// Then getPKCS8Key() hits the cache and never shells out.

Try / catch

try {
  $pkcs8 = $public_key->getPKCS8Key();
} catch (PhutilProxyException $ex) {
  $cause = $ex->getPrevious(); // CommandException: real ssh-keygen stderr
  // Fallback: precompute via './bin/auth cache-pkcs8', or point PATH
  // at a real OpenSSH ssh-keygen build, then retry.
}

Prevention

When it happens

Trigger: The system ssh-keygen cannot re-encode the stored key into PKCS8 - classically macOS's bundled ssh-keygen (LibreSSL-era) that ignores '-m PKCS8' and emits RFC4716 instead, or a key body that passed storage validation but fails conversion on the host doing the conversion.

Common situations: Development installs on OSX hitting this on first PKCS8 conversion before any cache entry exists; hosts where /usr/bin/ssh-keygen is a vendor build with different '-m' behavior; SSH trust/cluster communication setups that need PKCS8 forms.

Related errors


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