{"record":{"id":"a07396ca4f944a46","repo":"phacility/phabricator","slug":"keyring-configuration-is-invalid-it-describes-mul","errorCode":null,"errorMessage":"Keyring configuration is invalid: it describes multiple keys with the same name (\"%s\"). Each key must have a unique name.","messagePattern":"Keyring configuration is invalid: it describes multiple keys with the same name \\(\"(.+?)\"\\)\\. Each key must have a unique name\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/files/keyring/PhabricatorKeyringConfigOptionType.php","lineNumber":49,"sourceCode":"          $spec,\n          array(\n            'name' => 'string',\n            'type' => 'string',\n            'material.base64' => 'string',\n            'default' => 'optional bool',\n          ));\n      } catch (Exception $ex) {\n        throw new Exception(\n          pht(\n            'Keyring configuration has an invalid key specification (at '.\n            'index \"%s\"): %s.',\n            $index,\n            $ex->getMessage()));\n      }\n\n      $name = $spec['name'];\n      if (isset($map[$name])) {\n        throw new Exception(\n          pht(\n            'Keyring configuration is invalid: it describes multiple keys '.\n            'with the same name (\"%s\"). Each key must have a unique name.',\n            $name));\n      }\n      $map[$name] = true;\n\n      if (idx($spec, 'default')) {\n        $defaults[] = $name;\n      }\n\n      $type = $spec['type'];\n      switch ($type) {\n        case 'aes-256-cbc':\n          if (!function_exists('openssl_encrypt')) {\n            throw new Exception(\n              pht(\n                'Keyring is configured with a \"%s\" key, but the PHP OpenSSL '.","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/files/keyring/PhabricatorKeyringConfigOptionType.php#L31-L67","documentation":"The keyring validator collects key names as it walks the list and rejects the config when a second entry reuses a name already seen. Key names are the lookup key for PhabricatorKeyring::getKey(), so duplicates would make key resolution ambiguous. Each entry must have a unique name.","triggerScenarios":"Copy-pasting a key entry for rotation and forgetting to change the name; merging two keyring configs that both contain a key named 'default' or 'prod'.","commonSituations":"Key rotation done by duplicating an entry and editing only the material; combining environment configs during a merge.","solutions":["Rename duplicates to unique, meaningful names (e.g. prod-2023, prod-2024) — this is also what enables later rotation","Remove stale entries you intended to replace instead of keeping both with the same name"],"exampleFix":"// before\n[\n  {\"name\": \"prod\", \"type\": \"aes-256-cbc\", \"material.base64\": \"<OLD>\", \"default\": true},\n  {\"name\": \"prod\", \"type\": \"aes-256-cbc\", \"material.base64\": \"<NEW>\"}\n]\n\n// after\n[\n  {\"name\": \"prod-2023\", \"type\": \"aes-256-cbc\", \"material.base64\": \"<OLD>\"},\n  {\"name\": \"prod-2024\", \"type\": \"aes-256-cbc\", \"material.base64\": \"<NEW>\", \"default\": true}\n]","handlingStrategy":"validation","validationCode":"$seen = array();\nforeach ($value as $spec) {\n  $name = $spec['name'];\n  if (isset($seen[$name])) {\n    // Duplicate key name \"{$name}\"; rename entries before saving.\n  }\n  $seen[$name] = true;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use dated, unique key names from day one so rotation never collides","When merging keyring configs, deduplicate by name and keep one material per name"],"tags":["config","keyring","validation","phabricator"],"backgroundTag":"config-validation-failed","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}