phacility/phabricator · error · Exception
Configuration defines no task status with special attribute
Error message
Configuration defines no task status with special attribute "%s", but you must specify a status which fills this special role.
What it means
After scanning every maniphest.statuses entry, the validator requires that the three mandatory special roles — SPECIAL_DEFAULT, SPECIAL_CLOSED, SPECIAL_DUPLICATE — each appear exactly once. If none of the statuses carries a given special attribute, this Exception names the missing role. Without them Phabricator could not pick a status for new tasks, closing, or duplicates.
Source
Thrown at src/applications/maniphest/constants/ManiphestTaskStatus.php:390
}
$special_map[$special] = $key;
}
// NOTE: We're not explicitly validating that we have at least one open
// and one closed status, because the DEFAULT and CLOSED specials imply
// that to be true. If those change in the future, that might become a
// reasonable thing to validate.
$required = array(
self::SPECIAL_DEFAULT,
self::SPECIAL_CLOSED,
self::SPECIAL_DUPLICATE,
);
foreach ($required as $required_special) {
if (!isset($special_map[$required_special])) {
throw new Exception(
pht(
'Configuration defines no task status with special attribute '.
'"%s", but you must specify a status which fills this special '.
'role.',
$required_special));
}
}
}
}
View on GitHub (pinned to 5720a38cfe)
Solutions
- Ensure one status has "special": "default" (an open one), one has "special": "closed" (a closed one), and one has "special": "duplicate" (a closed one).
- Instead of removing an unwanted status, mark it "disabled": true so the special roles survive.
- Start from the shipped default maniphest.statuses map and modify entries rather than building one empty.
Example fix
// before
array(
'open' => array('name' => 'Open'),
'resolved' => array('name' => 'Resolved', 'closed' => true),
) // no special roles -> throws
// after
array(
'open' => array('name' => 'Open', 'special' => 'default'),
'resolved' => array('name' => 'Resolved', 'closed' => true, 'special' => 'closed'),
'duplicate' => array('name' => 'Duplicate', 'closed' => true, 'special' => 'duplicate'),
) Defensive patterns
Strategy: validation
Validate before calling
$roles = array();
foreach ($statuses as $constant => $spec) {
if (!empty($spec['special'])) $roles[$spec['special']] = $constant;
}
foreach (array('default', 'closed', 'duplicate') as $required) {
if (!isset($roles[$required])) {
throw new InvalidArgumentException("No status with special '$required'");
}
} Prevention
- Always define default, closed, and duplicate special roles in maniphest.statuses.
- Disable unwanted statuses with "disabled": true instead of deleting them.
- Start from the shipped default map when customizing.
When it happens
Trigger: A maniphest.statuses config where no entry has "special": "duplicate" (or "default", or "closed") — e.g. a from-scratch config that only lists open and resolved without special markers.
Common situations: Writing a minimal custom status list for the first time and not knowing about required special roles. Deleting a status (like 'duplicate') entirely instead of disabling it. Copying an example config that omitted the special fields.
Related errors
- Key "%s" is not a valid status constant. Status constants mu
- Value for key "%s" should be a dictionary.
- Task status ("%s") has unrecognized value for "locked" confi
- Configuration has two statuses both marked with the special
- Status "%s" is marked as default, but it is a closed status.
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/ae3f24deb1bb138e.
Report an issue: GitHub.