phacility/phabricator · error · Exception

No key "%s" exists in keyring.

Error message

No key "%s" exists in keyring.

What it means

PhabricatorKeyring::getKey() throws when the requested key name is absent from the in-memory keyring, which is lazily built from the 'keyring' config option. It surfaces when a file's stored key name (in its format properties) or a caller-selected name does not exist in config — typically after a key was deleted or config drifted between environments. Key lookup is by exact name string.

Source

Thrown at src/applications/files/keyring/PhabricatorKeyring.php:16

<?php

final class PhabricatorKeyring extends Phobject {

  private static $hasReadConfiguration;
  private static $keyRing = array();

  public static function addKey($spec) {
    self::$keyRing[$spec['name']] = $spec;
  }

  public static function getKey($name, $type) {
    self::readConfiguration();

    if (empty(self::$keyRing[$name])) {
      throw new Exception(
        pht(
          'No key "%s" exists in keyring.',
          $name));
    }

    $spec = self::$keyRing[$name];

    $material = base64_decode($spec['material.base64'], true);
    return new PhutilOpaqueEnvelope($material);
  }

  public static function getDefaultKeyName($type) {
    self::readConfiguration();

    foreach (self::$keyRing as $name => $key) {
      if (!empty($key['default'])) {
        return $name;
      }

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Re-add the missing key under the exact same name to the keyring config — names, not material, drive the lookup
  2. Check the stored key name (file format properties) and the --key argument for typos
  3. Verify every node and CLI context that reads files has the same keyring config

Example fix

# before: file encrypted with key "prod-2023" which was removed
# "keyring": [ { "name": "prod-2024", "type": "aes-256-cbc", "material.base64": "<NEW>", "default": true } ]

# after: re-add the old key so existing files resolve
# "keyring": [
#   { "name": "prod-2024", "type": "aes-256-cbc", "material.base64": "<NEW>", "default": true },
#   { "name": "prod-2023", "type": "aes-256-cbc", "material.base64": "<OLD>" }
# ]
Defensive patterns

Strategy: validation

Validate before calling

// Before touching an encrypted file or passing --key, confirm the key is configured:
function keyringHasKey($name) {
  foreach (PhabricatorEnv::getEnvConfig('keyring') as $spec) {
    if (idx($spec, 'name') === $name) {
      return true;
    }
  }
  return false;
}
if (!keyringHasKey($key_name)) {
  // Fail with a clear message instead of letting PhabricatorKeyring::getKey() throw.
}

Type guard

function keyringHasKey($name) {
  foreach (PhabricatorEnv::getEnvConfig('keyring') as $spec) {
    if (idx($spec, 'name') === $name) {
      return true;
    }
  }
  return false;
}

Prevention

When it happens

Trigger: Reading an AES-256-encrypted file whose stored key name was deleted from keyring config; running `./bin/files encode --key missing-name ...`; a multi-node deployment where one web/worker node's keyring config lacks the key.

Common situations: Cleaning up seemingly unused keys while old files still reference them; per-environment config drift; typos in the --key argument.

Related errors


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