{"record":{"id":"d4968e3594ebd6e9","repo":"phacility/phabricator","slug":"edge-transaction-includes-edge-of-type-s-but-t","errorCode":null,"errorMessage":"Edge transaction includes edge of type '%s', but transaction is of type '%s'. Each edge transaction must alter edges of only one type.","messagePattern":"Edge transaction includes edge of type '(.+?)', but transaction is of type '(.+?)'\\. Each edge transaction must alter edges of only one type\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php","lineNumber":2737,"sourceCode":"            break;\n          default:\n            throw new Exception(\n              pht(\n                'Transaction edge specification contains unexpected key \"%s\".',\n                $key));\n        }\n      }\n    }\n\n    $edge['dst'] = $dst_phid;\n\n    $edge_type = $xaction->getMetadataValue('edge:type');\n    if (empty($edge['type'])) {\n      $edge['type'] = $edge_type;\n    } else {\n      if ($edge['type'] != $edge_type) {\n        $this_type = $edge['type'];\n        throw new Exception(\n          pht(\n            \"Edge transaction includes edge of type '%s', but \".\n            \"transaction is of type '%s'. Each edge transaction \".\n            \"must alter edges of only one type.\",\n            $this_type,\n            $edge_type));\n      }\n    }\n\n    if (!isset($edge['data'])) {\n      $edge['data'] = array();\n    }\n\n    return $edge;\n  }\n\n  protected function sortTransactions(array $xactions) {\n    $head = array();","sourceCodeStart":2719,"sourceCodeEnd":2755,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php#L2719-L2755","documentation":"A single edge transaction alters edges of exactly one edge type, recorded in the transaction's 'edge:type' metadata. If an edge specification sets an explicit 'type' that differs from that metadata, normalizeEdgeTransactionValue() throws this exception.","triggerScenarios":"Building a TYPE_EDGE transaction with setMetadataValue('edge:type', X) while an edge spec in the delta contains array('type' => Y) with Y != X, e.g. mixing MEMBER (52) and SUBSCRIBER edges in one transaction.","commonSituations":"Code that copies edge specs from a different edge type (e.g. reusing a project-member spec for subscribers); refactoring that changes the transaction's edge type but not hardcoded spec 'type' values; specs sourced from raw edge table rows of a different relation.","solutions":["Omit 'type' from the spec entirely; it defaults to the transaction's 'edge:type' metadata.","If set explicitly, make the spec 'type' equal the transaction's edge:type value.","Split edges of different relations into one transaction per edge type."],"exampleFix":"// before\n$xaction->setMetadataValue('edge:type', 52);\n$xaction->setNewValue(array('+' => array(\n  $phid => array('type' => 4),\n)));\n\n// after\n$xaction->setMetadataValue('edge:type', 52);\n$xaction->setNewValue(array('+' => array(\n  $phid => array(),\n)));","handlingStrategy":"validation","validationCode":"$edge_type = $xaction->getMetadataValue('edge:type');\nforeach ($edge_list as $dst => $spec) {\n  if (is_array($spec) && isset($spec['type']) && $spec['type'] != $edge_type) {\n    unset($spec['type']); // let it default to the transaction's edge type\n    $edge_list[$dst] = $spec;\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set the edge type once via setMetadataValue('edge:type', ...) and omit 'type' in specs.","Use one transaction per edge relation instead of mixing relations in a delta."],"tags":["phabricator","transactions","edges","validation"],"backgroundTag":"transaction-validation-failed","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}