phacility/phabricator · error · Exception

Status rule value should be a string, but is not (value is "

Error message

Status rule value should be a string, but is not (value is "%s").

What it means

Thrown by assertValidRuleRecordFormat() when the stored value of a 'task.status' trigger rule is not a string. It runs in PhabricatorProjectTriggerRule::setRecord() on every load, because assertValidRuleRecordValue() will use the value as a status key into ManiphestTaskStatus::getTaskStatusMap().

Source

Thrown at src/applications/project/trigger/PhabricatorProjectTriggerManiphestStatusRule.php:14

<?php

final class PhabricatorProjectTriggerManiphestStatusRule
  extends PhabricatorProjectTriggerRule {

  const TRIGGERTYPE = 'task.status';

  public function getSelectControlName() {
    return pht('Change status to');
  }

  protected function assertValidRuleRecordFormat($value) {
    if (!is_string($value)) {
      throw new Exception(
        pht(
          'Status rule value should be a string, but is not (value is "%s").',
          phutil_describe_type($value)));
    }
  }

  protected function assertValidRuleRecordValue($value) {
    $map = ManiphestTaskStatus::getTaskStatusMap();
    if (!isset($map[$value])) {
      throw new Exception(
        pht(
          'Task status value ("%s") is not a valid task status. '.
          'Valid statues are: %s.',
          $value,
          implode(', ', array_keys($map))));
    }
  }

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Locate the row: SELECT * FROM phabricator_project_trigger_rule_record WHERE type='task.status'; and inspect value.
  2. Rewrite the value to a string status key, e.g. "resolved", via the trigger editor or repair script.
  3. Correct any import/migration logic to store scalar status keys.
  4. Confirm the workboard renders after the fix.

Example fix

// before
$value = array('resolved');

// after
$value = 'resolved';
Defensive patterns

Strategy: type-guard

Validate before calling

if (!is_string($value)) {
  throw new InvalidArgumentException('status value must be a string key');
}

Type guard

function isStatusRuleValue($value) {
  return is_string($value)
    && isset(ManiphestTaskStatus::getTaskStatusMap()[$value]);
}

Try / catch

try {
  $rule->setRecord($record);
} catch (Exception $ex) {
  phlog('Corrupt task.status record '.$record->getID());
  continue;
}

Prevention

When it happens

Trigger: A task.status rule whose value column holds an array, integer, or null instead of a status key string like 'open' or 'resolved'. Any load path — workboard render, trigger edit, card drop — throws from setRecord().

Common situations: Hand-edited or imported rows with wrong JSON shape; a custom writer reused the array format of tokenizer rules for the status rule; older version wrote a different shape.

Related errors


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