{"record":{"id":"0064a0d55d7ae629","repo":"phacility/phabricator","slug":"transactions-have-no-effect","errorCode":null,"errorMessage":"Transactions have no effect:","messagePattern":"Transactions have no effect:","errorType":"exception","errorClass":"PhabricatorApplicationTransactionNoEffectException","httpStatus":null,"severity":"warning","filePath":"src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php","lineNumber":2824,"sourceCode":"    // group, these transactions are junk.\n    if (count($meta_xactions) == count($xactions)) {\n      $no_effect = $xactions;\n      $any_effect = false;\n    }\n\n    if (!$no_effect) {\n      return $xactions;\n    }\n\n    // If none of the transactions have an effect, the meta-transactions also\n    // have no effect. Add them to the \"no effect\" list so we get a full set\n    // of errors for everything.\n    if (!$any_effect && !$has_comment) {\n      $no_effect += $meta_xactions;\n    }\n\n    if (!$this->getContinueOnNoEffect() && !$this->getIsPreview()) {\n      throw new PhabricatorApplicationTransactionNoEffectException(\n        $no_effect,\n        $any_effect,\n        $has_comment);\n    }\n\n    if (!$any_effect && !$has_comment) {\n      // If we only have empty comment transactions, just drop them all.\n      return array();\n    }\n\n    foreach ($no_effect as $key => $xaction) {\n      if ($xaction->hasComment()) {\n        $xaction->setTransactionType($type_comment);\n        $xaction->setOldValue(null);\n        $xaction->setNewValue(null);\n      } else {\n        unset($xactions[$key]);\n      }","sourceCodeStart":2806,"sourceCodeEnd":2842,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php#L2806-L2842","documentation":"PhabricatorApplicationTransactionNoEffectException is thrown when every transaction in the group would leave the object unchanged (new value equals old value, no comments added). The editor raises it unless setContinueOnNoEffect(true) or setIsPreview(true) is set, so callers notice accidental no-op edits.","triggerScenarios":"Calling applyTransactions() with a transaction whose new value already equals the stored value (e.g. setting a task's owner to its current owner, or adding a subscriber who is already subscribed) while the editor has neither ContinueOnNoEffect nor preview mode enabled.","commonSituations":"Daemons or import scripts that replay state without first checking current values; Conduit callers submitting full-form transactions where nothing changed; UI code that forgets to setContinueOnNoEffect(true) when the edit form always submits all fields.","solutions":["Filter out no-op transactions before applying: skip any whose getNewValue() equals getOldValue() and that carry no comment.","Call setContinueOnNoEffect(true) on the editor when a partial no-op is acceptable (this is what edit forms do).","Catch PhabricatorApplicationTransactionNoEffectException and use getTransactions()/hasAnyEffect() to decide whether to drop the group or continue.","For previews, setIsPreview(true)."],"exampleFix":"// before\n$editor->applyTransactions($object, $xactions);\n\n// after\n$editor->setContinueOnNoEffect(true)\n  ->applyTransactions($object, $xactions);","handlingStrategy":"try-catch","validationCode":"// Drop no-op transactions before applying\n$xactions = array_filter($xactions, function ($xaction) {\n  if ($xaction->hasComment()) {\n    return true;\n  }\n  return $xaction->getNewValue() != $xaction->getOldValue();\n});\nif (!$xactions) {\n  return; // nothing to do\n}","typeGuard":null,"tryCatchPattern":"try {\n  $editor->applyTransactions($object, $xactions);\n} catch (PhabricatorApplicationTransactionNoEffectException $ex) {\n  // Options: drop the no-effect group, or continue past it\n  if (!$ex->hasAnyEffect() && !$ex->hasComment()) {\n    return; // pure no-op, ignore\n  }\n  $xactions = $ex->getTransactions();\n  $editor->setContinueOnNoEffect(true)\n    ->applyTransactions($object, $xactions);\n}","preventionTips":["Compute the current value before building a transaction and skip unchanged fields.","Call setContinueOnNoEffect(true) in form-driven editors that always submit every field.","In scripts, compare desired state to loaded state and only emit real deltas."],"tags":["phabricator","transactions","no-op","editor"],"backgroundTag":"no-op-transaction","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}