{"record":{"id":"2f18b43903c4ac8a","repo":"phacility/phabricator","slug":"value-for-key-s-should-be-a-dictionary","errorCode":null,"errorMessage":"Value for key \"%s\" should be a dictionary.","messagePattern":"Value for key \"(.+?)\" should be a dictionary\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/maniphest/constants/ManiphestTaskPriority.php","lineNumber":216,"sourceCode":"    if (!is_array($config)) {\n      throw new Exception(\n        pht(\n          'Configuration is not valid. Maniphest priority configurations '.\n          'must be dictionaries.'));\n    }\n\n    $all_keywords = array();\n    foreach ($config as $key => $value) {\n      if (!ctype_digit((string)$key)) {\n        throw new Exception(\n          pht(\n            'Key \"%s\" is not a valid priority constant. Priority constants '.\n            'must be nonnegative integers.',\n            $key));\n      }\n\n      if (!is_array($value)) {\n        throw new Exception(\n          pht(\n            'Value for key \"%s\" should be a dictionary.',\n            $key));\n      }\n\n      PhutilTypeSpec::checkMap(\n        $value,\n        array(\n          'name' => 'string',\n          'keywords' => 'list<string>',\n          'short' => 'optional string',\n          'color' => 'optional string',\n          'disabled' => 'optional bool',\n        ));\n\n      $keywords = $value['keywords'];\n      foreach ($keywords as $keyword) {\n        if (!self::isValidPriorityKeyword($keyword)) {","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/maniphest/constants/ManiphestTaskPriority.php#L198-L234","documentation":"Each value in the maniphest.priorities dict must itself be an array/dict. After the digit-key check passes, !is_array($value) throws this Exception naming the key whose value is a scalar, null, or string. The subsequent PhutilTypeSpec::checkMap requires 'name' (string), 'keywords' (list<string>), and optional 'short', 'color', 'disabled'.","triggerScenarios":"A priority level whose value is a plain string: {\"90\": \"High\"}, or null: {\"90\": null}. JSON like {\"90\": [\"high\"]} decodes to a list, which passes is_array but then fails PhutilTypeSpec::checkMap with a different error — this specific message is for non-array values.","commonSituations":"Compact hand-written configs that map constant to label string, assuming keywords are derived automatically. Merging configs where one branch supplied only part of a spec. JSON null values from optional fields that were serialized anyway.","solutions":["Wrap each level in a full spec dict: {\"90\": {\"name\": \"High\", \"keywords\": [\"high\"]}}.","Make 'name' a string and 'keywords' a list of strings; add 'short', 'color', 'disabled' only when needed.","Lint your config with a script that asserts is_array($config[$key]) for every key before bin/config set."],"exampleFix":"// before\narray('90' => 'High')\n\n// after\narray('90' => array('name' => 'High', 'keywords' => array('high')))","handlingStrategy":"validation","validationCode":"foreach ($priorities as $key => $value) {\n  if (!is_array($value)) {\n    throw new InvalidArgumentException(\"Priority '$key' value must be a dict with name/keywords\");\n  }\n}","typeGuard":"function is_priority_spec($v) {\n  return is_array($v) && isset($v['name'], $v['keywords']) && is_string($v['name']) && is_array($v['keywords']);\n}","tryCatchPattern":null,"preventionTips":["Never map a priority constant to a bare string or null.","Omit unwanted priorities rather than nulling them.","Require 'name' (string) and 'keywords' (list<string>) in every spec."],"tags":["phabricator","maniphest","configuration","priority","type-validation"],"backgroundTag":"config-schema-validation","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}