{"record":{"id":"6667d1d57d34793f","repo":"phacility/phabricator","slug":"priority-rule-value-should-be-a-string-but-is-not","errorCode":null,"errorMessage":"Priority rule value should be a string, but is not (value is \"%s\").","messagePattern":"Priority rule value should be a string, but is not \\(value is \"(.+?)\"\\)\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/project/trigger/PhabricatorProjectTriggerManiphestPriorityRule.php","lineNumber":14,"sourceCode":"<?php\n\nfinal class PhabricatorProjectTriggerManiphestPriorityRule\n  extends PhabricatorProjectTriggerRule {\n\n  const TRIGGERTYPE = 'task.priority';\n\n  public function getSelectControlName() {\n    return pht('Change priority to');\n  }\n\n  protected function assertValidRuleRecordFormat($value) {\n    if (!is_string($value)) {\n      throw new Exception(\n        pht(\n          'Priority rule value should be a string, but is not (value is \"%s\").',\n          phutil_describe_type($value)));\n    }\n  }\n\n  protected function assertValidRuleRecordValue($value) {\n    $map = ManiphestTaskPriority::getTaskPriorityMap();\n    if (!isset($map[$value])) {\n      throw new Exception(\n        pht(\n          'Task priority value (\"%s\") is not a valid task priority. '.\n          'Valid priorities are: %s.',\n          $value,\n          implode(', ', array_keys($map))));\n    }\n  }\n","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/project/trigger/PhabricatorProjectTriggerManiphestPriorityRule.php#L1-L32","documentation":"Thrown by assertValidRuleRecordFormat() when the stored value of a 'task.priority' trigger rule is not a string. The check runs in PhabricatorProjectTriggerRule::setRecord() on every load of the rule record, because the rest of the rule treats the value as a priority keyword string looked up in ManiphestTaskPriority::getTaskPriorityMap().","triggerScenarios":"A task.priority rule whose value column holds an integer (e.g. 100 instead of '100'), an array, or null. Loading the trigger on a workboard, editing it, or dropping a card onto its column invokes setRecord() and throws immediately.","commonSituations":"Import/migration wrote the numeric priority as a PHP/JSON number; hand-edited DB row; custom code built the record with an int from getTaskPriorityMap() keys without casting.","solutions":["Find the offending row: SELECT * FROM phabricator_project_trigger_rule_record WHERE type='task.priority'; and check the value type.","Rewrite the value as a string keyword, e.g. \"100\", via the editor or a repair script.","Fix import code to cast priority keywords to strings before storing.","Reload the workboard/trigger to confirm the rule renders."],"exampleFix":"// before\n$value = 100;\n\n// after\n$value = '100';","handlingStrategy":"type-guard","validationCode":"// Before writing a task.priority rule record value:\nif (!is_string($value)) {\n  throw new InvalidArgumentException('priority value must be a string keyword');\n}","typeGuard":"function isPriorityRuleValue($value) {\n  return is_string($value)\n    && isset(ManiphestTaskPriority::getTaskPriorityMap()[$value]);\n}","tryCatchPattern":"try {\n  $rule->setRecord($record);\n} catch (Exception $ex) {\n  phlog('Corrupt task.priority record '.$record->getID());\n  continue; // skip rule, keep board rendering\n}","preventionTips":["Cast priority keywords to strings when generating records programmatically.","JSON-encode values with JSON_FORCE_OBJECT-free plain encode; verify with json_decode types.","Add a repair script that type-checks every rule record value against its rule class."],"tags":["php","phabricator","project-triggers","workboard","data-corruption"],"backgroundTag":"stored-config-validation-failed","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}