phacility/phabricator · error · Exception

Value for key "%s" should be a dictionary.

Error message

Value for key "%s" should be a dictionary.

What it means

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'.

Source

Thrown at src/applications/maniphest/constants/ManiphestTaskPriority.php:216

    if (!is_array($config)) {
      throw new Exception(
        pht(
          'Configuration is not valid. Maniphest priority configurations '.
          'must be dictionaries.'));
    }

    $all_keywords = array();
    foreach ($config as $key => $value) {
      if (!ctype_digit((string)$key)) {
        throw new Exception(
          pht(
            'Key "%s" is not a valid priority constant. Priority constants '.
            'must be nonnegative integers.',
            $key));
      }

      if (!is_array($value)) {
        throw new Exception(
          pht(
            'Value for key "%s" should be a dictionary.',
            $key));
      }

      PhutilTypeSpec::checkMap(
        $value,
        array(
          'name' => 'string',
          'keywords' => 'list<string>',
          'short' => 'optional string',
          'color' => 'optional string',
          'disabled' => 'optional bool',
        ));

      $keywords = $value['keywords'];
      foreach ($keywords as $keyword) {
        if (!self::isValidPriorityKeyword($keyword)) {

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Wrap each level in a full spec dict: {"90": {"name": "High", "keywords": ["high"]}}.
  2. Make 'name' a string and 'keywords' a list of strings; add 'short', 'color', 'disabled' only when needed.
  3. Lint your config with a script that asserts is_array($config[$key]) for every key before bin/config set.

Example fix

// before
array('90' => 'High')

// after
array('90' => array('name' => 'High', 'keywords' => array('high')))
Defensive patterns

Strategy: validation

Validate before calling

foreach ($priorities as $key => $value) {
  if (!is_array($value)) {
    throw new InvalidArgumentException("Priority '$key' value must be a dict with name/keywords");
  }
}

Type guard

function is_priority_spec($v) {
  return is_array($v) && isset($v['name'], $v['keywords']) && is_string($v['name']) && is_array($v['keywords']);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/2f18b43903c4ac8a. Report an issue: GitHub.