{"record":{"id":"eb34531fa4f3c062","repo":"phacility/phabricator","slug":"menu-contains-duplicate-items-with-key-s","errorCode":null,"errorMessage":"Menu contains duplicate items with key '%s'!","messagePattern":"Menu contains duplicate items with key '(.+?)'!","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/view/phui/PHUIListView.php","lineNumber":162,"sourceCode":"      if ($item->getKey() == $key) {\n        return $item;\n      }\n    }\n\n    return null;\n  }\n\n  public function getItems() {\n    return $this->items;\n  }\n\n  public function willRender() {\n    $key_map = array();\n    foreach ($this->items as $item) {\n      $key = $item->getKey();\n      if ($key !== null) {\n        if (isset($key_map[$key])) {\n          throw new Exception(\n            pht(\"Menu contains duplicate items with key '%s'!\", $key));\n        }\n        $key_map[$key] = $item;\n      }\n    }\n  }\n\n  protected function getTagName() {\n    return 'ul';\n  }\n\n  public function setType($type) {\n    $this->type = $type;\n    return $this;\n  }\n\n  protected function getTagAttributes() {\n    require_celerity_resource('phui-list-view-css');","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/view/phui/PHUIListView.php#L144-L180","documentation":"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.","triggerScenarios":"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'.","commonSituations":"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.","solutions":["Give every item a unique key derived from the data, e.g. ->setKey('project-'.$project->getID()).","Before adding, check $list->getItem($key) and skip or replace the existing item instead of adding a second one.","When merging menus, re-key or de-duplicate entries before adding them."],"exampleFix":"// before\nforeach ($projects as $project) {\n  $list->addMenuItem(\n    id(new PHUIListItemView())\n      ->setKey('project') // same key every iteration: throws in willRender()\n      ->setName($project->getName()));\n}\n\n// after\nforeach ($projects as $project) {\n  $list->addMenuItem(\n    id(new PHUIListItemView())\n      ->setKey('project-'.$project->getID())\n      ->setName($project->getName()));\n}","handlingStrategy":"validation","validationCode":"$key = $item->getKey();\nif ($key !== null && $list->getItem($key)) {\n  return; // duplicate: skip or replace, do not add\n}\n$list->addMenuItem($item);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["The library checks duplicates only in willRender(), late: validate keys at add time yourself.","Derive keys from unique data (IDs, PHIDs), never fixed strings inside loops.","De-duplicate when merging menus from multiple sources."],"tags":["php","phabricator","menu","duplicate-key","list-view"],"backgroundTag":"duplicate-menu-key","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}