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
- 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
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
- 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
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
- No AES256 key is specified in the keyring as a default encry
- Keyring specifies an invalid key ("%s"): key material should
- Keyring configuration is invalid: it describes a key with ty
- Failed to openssl_decrypt() data: %s
- Keyring configuration is not valid: value must be a list of
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/8e35c4d6cc2425ac.
Report an issue: GitHub.