phacility/phabricator · error · Exception

Menu contains duplicate items with key '%s'!

Error message

Menu contains duplicate items with key '%s'!

What it means

In willRender(), which the render pipeline invokes before producing HTML, PHUIListView builds a key map over its items and throws when two items share the same non-null key. The add methods (addMenuItem, addMenuItemAfter, addMenuItemToLabel) perform no duplicate detection, so a collision is caught only at render time, far from the code that added the duplicate.

Source

Thrown at src/view/phui/PHUIListView.php:162

      if ($item->getKey() == $key) {
        return $item;
      }
    }

    return null;
  }

  public function getItems() {
    return $this->items;
  }

  public function willRender() {
    $key_map = array();
    foreach ($this->items as $item) {
      $key = $item->getKey();
      if ($key !== null) {
        if (isset($key_map[$key])) {
          throw new Exception(
            pht("Menu contains duplicate items with key '%s'!", $key));
        }
        $key_map[$key] = $item;
      }
    }
  }

  protected function getTagName() {
    return 'ul';
  }

  public function setType($type) {
    $this->type = $type;
    return $this;
  }

  protected function getTagAttributes() {
    require_celerity_resource('phui-list-view-css');

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Give every item a unique key derived from the data, e.g. ->setKey('project-'.$project->getID()).
  2. Before adding, check $list->getItem($key) and skip or replace the existing item instead of adding a second one.
  3. When merging menus, re-key or de-duplicate entries before adding them.

Example fix

// before
foreach ($projects as $project) {
  $list->addMenuItem(
    id(new PHUIListItemView())
      ->setKey('project') // same key every iteration: throws in willRender()
      ->setName($project->getName()));
}

// after
foreach ($projects as $project) {
  $list->addMenuItem(
    id(new PHUIListItemView())
      ->setKey('project-'.$project->getID())
      ->setName($project->getName()));
}
Defensive patterns

Strategy: validation

Validate before calling

$key = $item->getKey();
if ($key !== null && $list->getItem($key)) {
  return; // duplicate: skip or replace, do not add
}
$list->addMenuItem($item);

Prevention

When it happens

Trigger: Two PHUIListItemView instances with the same setKey() value in one list — e.g. a loop that re-adds a constant key like 'project' per iteration, or merging two menus that both define 'edit'.

Common situations: Dynamically generated menus where the same action appears twice; combining default menu items with custom ones that reuse core keys; conditional code where both branches add the same key.

Related errors


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