{"record":{"id":"32cf52b633aceda0","repo":"phacility/phabricator","slug":"edge-transactions-must-have-destination-phids-as-i","errorCode":null,"errorMessage":"Edge transactions must have destination PHIDs as in edge lists (found key \"%s\" on transaction of type \"%s\").","messagePattern":"Edge transactions must have destination PHIDs as in edge lists \\(found key \"(.+?)\" on transaction of type \"(.+?)\"\\)\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php","lineNumber":2677,"sourceCode":"        $xaction,\n        $edge,\n        $dst_phid);\n    }\n\n    foreach ($new_rem as $dst_phid => $edge) {\n      unset($result[$dst_phid]);\n    }\n\n    return $result;\n  }\n\n  private function checkEdgeList($list, $edge_type) {\n    if (!$list) {\n      return;\n    }\n    foreach ($list as $key => $item) {\n      if (phid_get_type($key) === PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN) {\n        throw new Exception(\n          pht(\n            'Edge transactions must have destination PHIDs as in edge '.\n            'lists (found key \"%s\" on transaction of type \"%s\").',\n            $key,\n            $edge_type));\n      }\n      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(","sourceCodeStart":2659,"sourceCodeEnd":2695,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php#L2659-L2695","documentation":"In an edge delta list, each entry must be keyed by the destination PHID: checkEdgeList() verifies that phid_get_type() on the key returns a real type rather than PHID_TYPE_UNKNOWN. This exception fires when a list contains a key that is not a well-formed PHID.","triggerScenarios":"Passing an edge list keyed by usernames, monograms (e.g. #project), raw IDs, or malformed PHID strings (typo, truncation, whitespace) inside '+'/'-'/'=' values of a TYPE_EDGE transaction.","commonSituations":"Script converts user input like 'alice' or 'T123' directly into edge-list keys without resolving them to PHIDs first; data imported from an external system contains non-PHID identifiers; a PHID got mangled during transport or string concatenation.","solutions":["Resolve identifiers to PHIDs before building the transaction (e.g. PhabricatorObjectQuery with monograms, or the appropriate search endpoint).","Key every edge entry by its destination PHID: array('+' => array('PHID-PROJ-...' => 'PHID-PROJ-...')).","Sanitize/trim values when importing external data and log any token that does not start with 'PHID-'."],"exampleFix":"// before\n$new = array('+' => array('alice' => 'alice'));\n\n// after\n$user_phid = id(new PhabricatorPeopleUserFindEngine())\n  ->setViewer($viewer)\n  ->findUsers('alice'); // then use resolved PHID(s)\n$new = array('+' => array($user_phid => $user_phid));","handlingStrategy":"validation","validationCode":"// Resolve every identifier to a PHID before building the edge list\n$phids = array();\nforeach ($raw_identifiers as $identifier) {\n  $phid = id(new PhabricatorObjectQuery())\n    ->setViewer($viewer)\n    ->withNames(array($identifier))\n    ->executeOne();\n  if (!$phid) {\n    continue; // or collect an error for the user\n  }\n  $phids[] = $phid->getPHID();\n}\n$new = array('+' => array_fuse($phids));","typeGuard":"function isPhid($value) {\n  return is_string($value)\n    && preg_match('/^PHID-[A-Z]{4}-/', $value)\n    && phid_get_type($value) !== PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN;\n}","tryCatchPattern":null,"preventionTips":["Always resolve monograms/usernames to PHIDs before constructing transactions.","Reject or trim any token that does not start with 'PHID-' at the input boundary.","When importing external data, validate PHIDs in a pre-pass and log rejects instead of submitting them."],"tags":["phabricator","transactions","edges","phid","validation"],"backgroundTag":"invalid-phid-reference","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}