phacility/phabricator · error · Exception

Status "%s" is marked as the default status for closing task

Error message

Status "%s" is marked as the default status for closing tasks, but is not a closed status. It should be a closed status.

What it means

A status marked "special": "closed" is the status tasks move to on normal close, so it must itself be a closed status. The validator's SPECIAL_CLOSED case throws when that entry lacks "closed": true, because closing a task into an open status would corrupt open/closed semantics (burn-down, board behavior).

Source

Thrown at src/applications/maniphest/constants/ManiphestTaskStatus.php:354

            'attribute "%s" ("%s" and "%s"). There should be only one.',
            $special,
            $special_map[$special],
            $key));
      }

      switch ($special) {
        case self::SPECIAL_DEFAULT:
          if (!empty($value['closed'])) {
            throw new Exception(
              pht(
                'Status "%s" is marked as default, but it is a closed '.
                'status. The default status should be an open status.',
                $key));
          }
          break;
        case self::SPECIAL_CLOSED:
          if (empty($value['closed'])) {
            throw new Exception(
              pht(
                'Status "%s" is marked as the default status for closing '.
                'tasks, but is not a closed status. It should be a closed '.
                'status.',
                $key));
          }
          break;
        case self::SPECIAL_DUPLICATE:
          if (empty($value['closed'])) {
            throw new Exception(
              pht(
                'Status "%s" is marked as the status for closing tasks as '.
                'duplicates, but it is not a closed status. It should '.
                'be a closed status.',
                $key));
          }
          break;
      }

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Add "closed": true to whichever status carries "special": "closed".
  2. Keep the canonical pattern: close-target statuses (resolved, invalid, wontfix) all set "closed": true; only the special one is REQUIRED to.
  3. Diff your custom statuses against the shipped defaults to confirm every special status has matching closed-ness.

Example fix

// before
'resolved' => array('name' => 'Resolved', 'special' => 'closed'),

// after
'resolved' => array('name' => 'Resolved', 'closed' => true, 'special' => 'closed'),
Defensive patterns

Strategy: validation

Validate before calling

foreach ($statuses as $constant => $spec) {
  if (idx($spec, 'special') === 'closed' && empty($spec['closed'])) {
    throw new InvalidArgumentException("Close-default status '$constant' must set closed: true");
  }
}

Prevention

When it happens

Trigger: maniphest.statuses entry like {"resolved": {"name": "Resolved", "special": "closed"}} with no "closed": true — renaming or rebuilding statuses and dropping the closed flag from the close-target.

Common situations: Editing display names by rewriting whole entries and omitting the closed flag. Introducing a custom 'Completed' close status copied from an open status template but keeping the special role.

Related errors


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