{"record":{"id":"772c2c7bf262a203","repo":"phacility/phabricator","slug":"keyring-configuration-is-not-valid-each-entry-in","errorCode":null,"errorMessage":"Keyring configuration is not valid: each entry in the list must be a dictionary describing an encryption key, but the value with index \"%s\" is not a dictionary.","messagePattern":"Keyring configuration is not valid: each entry in the list must be a dictionary describing an encryption key, but the value with index \"(.+?)\" is not a dictionary\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/files/keyring/PhabricatorKeyringConfigOptionType.php","lineNumber":16,"sourceCode":"<?php\n\nfinal class PhabricatorKeyringConfigOptionType\n  extends PhabricatorConfigJSONOptionType {\n\n  public function validateOption(PhabricatorConfigOption $option, $value) {\n    if (!is_array($value)) {\n      throw new Exception(\n        pht(\n          'Keyring configuration is not valid: value must be a '.\n          'list of encryption keys.'));\n    }\n\n    foreach ($value as $index => $spec) {\n      if (!is_array($spec)) {\n        throw new Exception(\n          pht(\n            'Keyring configuration is not valid: each entry in the list must '.\n            'be a dictionary describing an encryption key, but the value '.\n            'with index \"%s\" is not a dictionary.',\n            $index));\n      }\n    }\n\n\n    $map = array();\n    $defaults = array();\n    foreach ($value as $index => $spec) {\n      try {\n        PhutilTypeSpec::checkMap(\n          $spec,\n          array(\n            'name' => 'string',\n            'type' => 'string',","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/files/keyring/PhabricatorKeyringConfigOptionType.php#L1-L34","documentation":"Each element of the 'keyring' config list must itself be a dictionary describing one encryption key; this variant is thrown when the entry at the printed index is not an array. It is the second check in PhabricatorKeyringConfigOptionType::validateOption(), after the top-level list check. Typically the list contains bare strings instead of objects.","triggerScenarios":"Setting keyring to [\"key1\",\"key2\"]; a list where one entry is a dict and another is a scalar; JSON written as an object keyed by name instead of a list of objects with a name field.","commonSituations":"Hand-writing the keyring JSON for the first time; converting from a name=>material map format into the required list-of-dicts shape.","solutions":["Wrap every entry in an object with the required fields: name, type, material.base64 (and optional default)","If you wrote a JSON object keyed by key names, convert it to a list where each item has a \"name\" field"],"exampleFix":"// before\n[\"prod-2024\", \"prod-2023\"]\n\n// after\n[\n  {\"name\": \"prod-2024\", \"type\": \"aes-256-cbc\", \"material.base64\": \"...\", \"default\": true},\n  {\"name\": \"prod-2023\", \"type\": \"aes-256-cbc\", \"material.base64\": \"...\"}\n]","handlingStrategy":"validation","validationCode":"foreach ($value as $index => $spec) {\n  if (!is_array($spec)) {\n    // Entry {$index} must be a dictionary with name/type/material.base64.\n  }\n}","typeGuard":"function isKeyringEntryDict($spec) {\n  return is_array($spec);\n}","tryCatchPattern":null,"preventionTips":["Every list element must be an object; never mix strings into the keyring list","Lint the JSON structure in CI when keyring config lives in a repo"],"tags":["config","json","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"}