{"record":{"id":"9b1ee6b83e7222a9","repo":"phacility/phabricator","slug":"specify-enable-or-disable-but-not-both","errorCode":null,"errorMessage":"Specify \"--enable\" or \"--disable\", but not both.","messagePattern":"Specify \"--enable\" or \"--disable\", but not both\\.","errorType":"console","errorClass":"PhutilArgumentUsageException","httpStatus":null,"severity":"warning","filePath":"src/applications/herald/management/HeraldRuleManagementWorkflow.php","lineNumber":64,"sourceCode":"\n    $rule = id(new HeraldRuleQuery())\n      ->setViewer($viewer)\n      ->withIDs(array($rule_id))\n      ->executeOne();\n    if (!$rule) {\n      throw new PhutilArgumentUsageException(\n        pht(\n          'Unable to load Herald rule with ID or monogram \"%s\".',\n          $rule_name));\n    }\n\n    $is_disable = $args->getArg('disable');\n    $is_enable = $args->getArg('enable');\n\n    $xactions = array();\n\n    if ($is_disable && $is_enable) {\n      throw new PhutilArgumentUsageException(\n        pht(\n          'Specify \"--enable\" or \"--disable\", but not both.'));\n    } else if ($is_disable || $is_enable) {\n      $xactions[] = $rule->getApplicationTransactionTemplate()\n        ->setTransactionType(HeraldRuleDisableTransaction::TRANSACTIONTYPE)\n        ->setNewValue($is_disable);\n    }\n\n    if (!$xactions) {\n      throw new PhutilArgumentUsageException(\n        pht(\n          'Use flags to specify at least one edit to apply to the '.\n          'rule (for example, use \"--disable\" to disable a rule).'));\n    }\n\n    $herald_phid = id(new PhabricatorHeraldApplication())->getPHID();\n\n    $editor = $rule->getApplicationTransactionEditor()","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/herald/management/HeraldRuleManagementWorkflow.php#L46-L82","documentation":"PhutilArgumentUsageException thrown by HeraldRuleManagementWorkflow when both --enable and --disable are passed. The two flags map to the same HeraldRuleDisableTransaction with opposite new-values, so passing both is contradictory; the workflow refuses rather than guessing an order.","triggerScenarios":"Running 'bin/herald rule --rule H1 --enable --disable'. The check is a simple $is_disable && $is_enable before any transaction is queued.","commonSituations":"Copy-pasted command lines accumulated flags from a previous invocation; scripts built by concatenating optional flags without mutual exclusion; muscle memory adding --disable while the command already contained --enable.","solutions":["Pass exactly one of the two flags: --disable to disable, --enable to enable.","In scripts, model the state as a single variable and emit one flag: [ \"$STATE\" = off ] && FLAG=--disable || FLAG=--enable.","Clear stale shell history edits before re-running the composed command."],"exampleFix":"# before\nbin/herald rule --rule H1 --enable --disable\n\n# after\nbin/herald rule --rule H1 --disable","handlingStrategy":"validation","validationCode":"$is_disable = (bool)$args->getArg('disable');\n$is_enable = (bool)$args->getArg('enable');\nif ($is_disable && $is_enable) {\n  // reject before building transactions: exactly one flag allowed\n}","typeGuard":"function exactlyOneOf(/* bool ... */ $flags) {\n  return count(array_filter($flags)) === 1;\n}","tryCatchPattern":"try {\n  $workflow->execute($args);\n} catch (PhutilArgumentUsageException $ex) {\n  // 'but not both' -> strip one flag and retry; state-changing ops are\n  // still safe because the workflow refuses before applying anything\n}","preventionTips":["Model enable/disable as one tri-state variable in scripts so both flags can never be emitted together.","Audit copy-pasted commands for accumulated flags before running them."],"tags":["herald","phabricator","cli","usage-error","conflicting-flags"],"backgroundTag":"conflicting-cli-flags","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}