{"record":{"id":"8e35c4d6cc2425ac","repo":"phacility/phabricator","slug":"no-key-s-exists-in-keyring","errorCode":null,"errorMessage":"No key \"%s\" exists in keyring.","messagePattern":"No key \"(.+?)\" exists in keyring\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/files/keyring/PhabricatorKeyring.php","lineNumber":16,"sourceCode":"<?php\n\nfinal class PhabricatorKeyring extends Phobject {\n\n  private static $hasReadConfiguration;\n  private static $keyRing = array();\n\n  public static function addKey($spec) {\n    self::$keyRing[$spec['name']] = $spec;\n  }\n\n  public static function getKey($name, $type) {\n    self::readConfiguration();\n\n    if (empty(self::$keyRing[$name])) {\n      throw new Exception(\n        pht(\n          'No key \"%s\" exists in keyring.',\n          $name));\n    }\n\n    $spec = self::$keyRing[$name];\n\n    $material = base64_decode($spec['material.base64'], true);\n    return new PhutilOpaqueEnvelope($material);\n  }\n\n  public static function getDefaultKeyName($type) {\n    self::readConfiguration();\n\n    foreach (self::$keyRing as $name => $key) {\n      if (!empty($key['default'])) {\n        return $name;\n      }","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/files/keyring/PhabricatorKeyring.php#L1-L34","documentation":"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.","triggerScenarios":"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.","commonSituations":"Cleaning up seemingly unused keys while old files still reference them; per-environment config drift; typos in the --key argument.","solutions":["Re-add the missing key under the exact same name to the keyring config — names, not material, drive the lookup","Check the stored key name (file format properties) and the --key argument for typos","Verify every node and CLI context that reads files has the same keyring config"],"exampleFix":"# before: file encrypted with key \"prod-2023\" which was removed\n# \"keyring\": [ { \"name\": \"prod-2024\", \"type\": \"aes-256-cbc\", \"material.base64\": \"<NEW>\", \"default\": true } ]\n\n# after: re-add the old key so existing files resolve\n# \"keyring\": [\n#   { \"name\": \"prod-2024\", \"type\": \"aes-256-cbc\", \"material.base64\": \"<NEW>\", \"default\": true },\n#   { \"name\": \"prod-2023\", \"type\": \"aes-256-cbc\", \"material.base64\": \"<OLD>\" }\n# ]","handlingStrategy":"validation","validationCode":"// Before touching an encrypted file or passing --key, confirm the key is configured:\nfunction keyringHasKey($name) {\n  foreach (PhabricatorEnv::getEnvConfig('keyring') as $spec) {\n    if (idx($spec, 'name') === $name) {\n      return true;\n    }\n  }\n  return false;\n}\nif (!keyringHasKey($key_name)) {\n  // Fail with a clear message instead of letting PhabricatorKeyring::getKey() throw.\n}","typeGuard":"function keyringHasKey($name) {\n  foreach (PhabricatorEnv::getEnvConfig('keyring') as $spec) {\n    if (idx($spec, 'name') === $name) {\n      return true;\n    }\n  }\n  return false;\n}","tryCatchPattern":null,"preventionTips":["Treat keyring keys as append-only: delete a key only after confirming no file references it","Distribute one keyring config to all nodes and CLI contexts that read files","Use stable, dated key names (prod-YYYY) so rotation never reuses or retypes names"],"tags":["encryption","keyring","config","files","phabricator"],"backgroundTag":"missing-encryption-key","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}