{"record":{"id":"05022beb7e8d5d2a","repo":"phacility/phabricator","slug":"transaction-edge-data-must-either-be-the-edge-phid","errorCode":null,"errorMessage":"Transaction edge data must either be the edge PHID or an edge specification dictionary.","messagePattern":"Transaction edge data must either be the edge PHID or an edge specification dictionary\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php","lineNumber":2702,"sourceCode":"      if (!is_array($item) && $item !== $key) {\n        throw new Exception(\n          pht(\n            'Edge transactions must have PHIDs or edge specs as values '.\n            '(found value \"%s\" on transaction of type \"%s\").',\n            $item,\n            $edge_type));\n      }\n    }\n  }\n\n  private function normalizeEdgeTransactionValue(\n    PhabricatorApplicationTransaction $xaction,\n    $edge,\n    $dst_phid) {\n\n    if (!is_array($edge)) {\n      if ($edge != $dst_phid) {\n        throw new Exception(\n          pht(\n            'Transaction edge data must either be the edge PHID or an edge '.\n            'specification dictionary.'));\n      }\n      $edge = array();\n    } else {\n      foreach ($edge as $key => $value) {\n        switch ($key) {\n          case 'src':\n          case 'dst':\n          case 'type':\n          case 'data':\n          case 'dateCreated':\n          case 'dateModified':\n          case 'seq':\n          case 'dataID':\n            break;\n          default:","sourceCodeStart":2684,"sourceCodeEnd":2720,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php#L2684-L2720","documentation":"normalizeEdgeTransactionValue() accepts an edge entry that is either the destination PHID as a plain scalar or an array specification. If the entry is a scalar that does not equal the destination PHID it was resolved to, this exception is thrown.","triggerScenarios":"An edge delta list entry whose scalar value points at a different PHID than its key (e.g., a set-list where key => value are two different objects), reaching normalizeEdgeTransactionValue() during transaction application.","commonSituations":"The same class of bug as the checkEdgeList() guard but arriving through a code path that normalizes values directly (set-lists merged from multiple sources, programmatically generated specs); data from external feeds pairing stale keys with updated values.","solutions":["Make scalar entries equal their own key: array($dst_phid => $dst_phid).","Put extra per-edge information in an array spec instead of a second PHID string.","Rebuild edge lists with array_fuse() from a single canonical list of destination PHIDs."],"exampleFix":"// before\n$edge = $other_phid; // scalar != $dst_phid\n$list[$dst_phid] = $edge;\n\n// after\n$list[$dst_phid] = $dst_phid;","handlingStrategy":"validation","validationCode":"foreach ($edge_list as $dst => $spec) {\n  if (!is_array($spec) && $spec !== $dst) {\n    throw new Exception(pht('Edge value must equal key %s.', $dst));\n  }\n}\n$xaction->setNewValue(array('=' => $edge_list));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep one source of truth for the destination PHID; derive both key and scalar value from it.","Prefer array specs (even empty arrays) when the value might ever carry data."],"tags":["phabricator","transactions","edges","validation"],"backgroundTag":"invalid-phid-reference","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}