phacility/phabricator · error · Exception
Project icons must have unique keys, but two icons share the
Error message
Project icons must have unique keys, but two icons share the same key ("%s"). What it means
Icon keys must be unique across the whole projects.icons list. While collecting keys into a lookup array, a second specification reusing an existing key throws and names the duplicated key, before default/milestone resolution continues.
Source
Thrown at src/applications/project/icon/PhabricatorProjectIconSet.php:255
if ($special !== null) {
if (empty($valid[$special])) {
throw new Exception(
pht(
'Icon special attribute "%s" is not valid. Recognized special '.
'attributes are: %s.',
$special,
implode(', ', array_keys($valid))));
}
}
}
$default = null;
$milestone = null;
$keys = array();
foreach ($config as $idx => $value) {
$key = $value['key'];
if (isset($keys[$key])) {
throw new Exception(
pht(
'Project icons must have unique keys, but two icons share the '.
'same key ("%s").',
$key));
} else {
$keys[$key] = true;
}
$is_disabled = idx($value, 'disabled');
$image = idx($value, 'image');
if ($image !== null) {
$builtin = idx($value, 'image');
$builtin_map = id(new PhabricatorFilesOnDiskBuiltinFile())
->getProjectBuiltinFiles();
$builtin_map = array_flip($builtin_map);
$root = dirname(phutil_get_library_root('phabricator'));View on GitHub (pinned to 5720a38cfe)
Solutions
- Rename one of the duplicates to an unused lowercase key (letters only).
- If you meant to replace a builtin icon, remove the original entry so only one spec carries that key.
Example fix
// before: two entries share key "tag"
[{"key":"tag","name":"Tag","icon":"fa-tags"}, {"key":"tag","name":"Tag2","icon":"fa-tag"}]
// after
[{"key":"tag","name":"Tag","icon":"fa-tags"}, {"key":"label","name":"Label","icon":"fa-tag"}] Defensive patterns
Strategy: validation
Validate before calling
$keys = array();
foreach ($config as $entry) {
if (isset($keys[$entry['key']])) {
throw new Exception('duplicate icon key: '.$entry['key']);
}
$keys[$entry['key']] = true;
} Type guard
function has_unique_icon_keys(array $config) {
$keys = array_column($config, 'key');
return count($keys) === count(array_unique($keys));
} Prevention
- When adding a custom icon, rename it or drop the builtin entry it replaces.
- Lint merged config fragments for duplicate keys before saving.
When it happens
Trigger: Appending a custom icon with "key": "tag" while the builtin tag icon is still in the list, or merging two config fragments that both define the same key.
Common situations: Extending the default list instead of replacing it, and merging icon configs from multiple sources.
Related errors
- Two authentication providers use the same provider key ('%s'
- Configuration must be a list of project icon specifications.
- Value for index "%s" should be a dictionary.
- Icon key "%s" is not a valid icon key. Icon keys must be 1-3
- Icon special attribute "%s" is not valid. Recognized special
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/c8f5eaa16c2cd163.
Report an issue: GitHub.