phacility/phabricator · error · Exception

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

Error message

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

What it means

Each element of projects.icons must itself be an array — one dictionary describing one icon. A scalar entry (string, number, bool) throws with the offending index; after this check, each dictionary's fields are verified by PhutilTypeSpec::checkMap.

Source

Thrown at src/applications/project/icon/PhabricatorProjectIconSet.php:203

  public static function getMilestoneIconKey() {
    $icons = self::getIconSpecifications();
    foreach ($icons as $icon) {
      if (idx($icon, 'special') === self::SPECIAL_MILESTONE) {
        return idx($icon, 'key');
      }
    }
    return null;
  }

  public static function validateConfiguration($config) {
    if (!is_array($config)) {
      throw new Exception(
        pht('Configuration must be a list of project icon specifications.'));
    }

    foreach ($config as $idx => $value) {
      if (!is_array($value)) {
        throw new Exception(
          pht(
            'Value for index "%s" should be a dictionary.',
            $idx));
      }

      PhutilTypeSpec::checkMap(
        $value,
        array(
          'key' => 'string',
          'name' => 'string',
          'icon' => 'string',
          'image' => 'optional string',
          'special' => 'optional string',
          'disabled' => 'optional bool',
          'default' => 'optional bool',
        ));

      if (!preg_match('/^[a-z]{1,32}\z/', $value['key'])) {

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Wrap every entry in an object with at least key, name, and icon.
  2. Decode the payload in a scratch script and assert every element is an array before saving.

Example fix

// before
[{"key":"tag","name":"Tag","icon":"fa-tags"}, "group"]
// after
[{"key":"tag","name":"Tag","icon":"fa-tags"},
 {"key":"group","name":"Group","icon":"fa-users"}]
Defensive patterns

Strategy: validation

Validate before calling

foreach ($config as $idx => $entry) {
  if (!is_array($entry)) {
    throw new Exception(sprintf('entry %d is not a dictionary', $idx));
  }
}

Type guard

function is_icon_spec($entry) {
  return is_array($entry)
    && isset($entry['key'], $entry['name'], $entry['icon']);
}

Prevention

When it happens

Trigger: A list like ["tag", {...}] where one entry is a bare string instead of a {"key": ...} dictionary.

Common situations: Hand-trimming config for brevity and replacing a dict with just its key, and merging config fragments from different sources.

Related errors


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