phacility/phabricator · error · Exception

Task status ("%s") has unrecognized value for "locked" confi

Error message

Task status ("%s") has unrecognized value for "locked" configuration ("%s"). Supported values are: "%s", "%s".

What it means

The optional 'locked' field of a maniphest.statuses entry may be boolean true/false, or one of the two string constants ManiphestTaskStatus::LOCKED_COMMENTS or LOCKED_EDITS ('locked-comments', 'locked-edits'). Any other value — a string like 'yes', an integer 1, or null-ish placeholders — throws this Exception listing the status, the bad value, and the two supported strings.

Source

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

          'mfa' => 'optional bool',
        ));
    }

    // Supported values are "comments" or "edits". For backward compatibility,
    // "true" is an alias of "comments".

    foreach ($config as $key => $value) {
      $locked = idx($value, 'locked', false);
      if ($locked === true || $locked === false) {
        continue;
      }

      if ($locked === self::LOCKED_EDITS ||
          $locked === self::LOCKED_COMMENTS) {
        continue;
      }

      throw new Exception(
        pht(
          'Task status ("%s") has unrecognized value for "locked" '.
          'configuration ("%s"). Supported values are: "%s", "%s".',
          $key,
          $locked,
          self::LOCKED_COMMENTS,
          self::LOCKED_EDITS));
    }

    $special_map = array();
    foreach ($config as $key => $value) {
      $special = idx($value, 'special');
      if (!$special) {
        continue;
      }

      if (isset($special_map[$special])) {
        throw new Exception(

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Use real JSON booleans for simple locking: "locked": true or "locked": false.
  2. Use the exact strings "locked-comments" or "locked-edits" to disable only comments or only edits on that status.
  3. Drop the 'locked' key entirely when the status should not be locked (false is the default).

Example fix

// before
'archived' => array('name' => 'Archived', 'locked' => 'true'),

// after
'archived' => array('name' => 'Archived', 'locked' => true),
// or: 'locked' => 'locked-comments'
Defensive patterns

Strategy: validation

Validate before calling

function is_valid_locked($v) {
  return $v === true || $v === false
    || $v === 'locked-comments' || $v === 'locked-edits';
}
foreach ($statuses as $constant => $spec) {
  if (isset($spec['locked']) && !is_valid_locked($spec['locked'])) {
    throw new InvalidArgumentException("Bad 'locked' for '$constant'");
  }
}

Type guard

function is_locked_value($v) { return $v === true || $v === false || $v === 'locked-comments' || $v === 'locked-edits'; }

Prevention

When it happens

Trigger: A config entry like {"archived": {"name": "Archived", "locked": "true"}} (string 'true' instead of boolean) or {"locked": 1}. The $locked === true/=== false and the two string comparisons all fail, so the Exception fires.

Common situations: Hand-written JSON where booleans were quoted. Scripts generating config from a CSV/spreadsheet where the locked column contains 'yes'/'no' or 1/0. Copying examples from forum posts that predate the string lock modes.

Related errors


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