phacility/phabricator · error · PhutilProxyException

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

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.

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.

Appendix: 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)