{"record":{"id":"216d92aebf9ab03a","repo":"phacility/phabricator","slug":"invalid-s-value-for-edge-transaction-value-sho","errorCode":null,"errorMessage":"Invalid '%s' value for Edge transaction. Value should contain only keys '%s' (add edges), '%s' (remove edges) and '%s' (set edges).","messagePattern":"Invalid '(.+?)' value for Edge transaction\\. Value should contain only keys '(.+?)' \\(add edges\\), '(.+?)' \\(remove edges\\) and '(.+?)' \\(set edges\\)\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php","lineNumber":2620,"sourceCode":"      unset($result[$phid]);\n    }\n\n    return array_values($result);\n  }\n\n  protected function getEdgeTransactionNewValue(\n    PhabricatorApplicationTransaction $xaction) {\n\n    $new = $xaction->getNewValue();\n    $new_add = idx($new, '+', array());\n    unset($new['+']);\n    $new_rem = idx($new, '-', array());\n    unset($new['-']);\n    $new_set = idx($new, '=', null);\n    unset($new['=']);\n\n    if ($new) {\n      throw new Exception(\n        pht(\n          \"Invalid '%s' value for Edge transaction. Value should contain only \".\n          \"keys '%s' (add edges), '%s' (remove edges) and '%s' (set edges).\",\n          'new',\n          '+',\n          '-',\n          '='));\n    }\n\n    $old = $xaction->getOldValue();\n\n    $lists = array($new_set, $new_add, $new_rem);\n    foreach ($lists as $list) {\n      $this->checkEdgeList($list, $xaction->getMetadataValue('edge:type'));\n    }\n\n    $result = array();\n    foreach ($old as $dst_phid => $edge) {","sourceCodeStart":2602,"sourceCodeEnd":2638,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php#L2602-L2638","documentation":"Edge transactions (projects, revert-to, dependencies, etc.) encode their new value as a delta dictionary keyed by '+' (add edges), '-' (remove edges) and '=' (set edges). getEdgeTransactionNewValue() removes those keys and throws if the 'new' value still contains any other key.","triggerScenarios":"Setting an edge transaction's new value to a flat array of PHIDs, a dict keyed by PHIDs, or with keys like 'add'/'remove' instead of '+'/'-'/'='. The throw happens while the editor applies the transaction, after value normalization begins.","commonSituations":"Conduit callers sending {\"value\": [\"PHID-...\"]} for project.setprojects-style endpoints; custom code constructing PhabricatorTransactions::TYPE_EDGE with setNewValue(array($dst_phid)); confusion because '=' here takes a list-or-dict of edges, not the same shape as PHID list transactions.","solutions":["Use only '+'/'-'/'=' keys: setNewValue(array('+' => array($dst_phid => $dst_phid))) to add, array('-' => ...) to remove, array('=' => ...) to set.","When calling Conduit, format edge values as {\"+\": [...]} / {\"-\": [...]} / {\"=\": [...]}.","Check the specific transaction type's expected shape in its getTransactionType() implementation if unsure."],"exampleFix":"// before\n$xaction->setNewValue(array($project_phid));\n\n// after\n$xaction->setNewValue(array('+' => array($project_phid => $project_phid)));","handlingStrategy":"type-guard","validationCode":"// Normalize an arbitrary edge payload into a legal delta\nfunction edge_delta(array $set = null, array $add = array(), array $rem = array()) {\n  if ($set !== null) {\n    return array('=' => array_fuse($set));\n  }\n  $delta = array();\n  if ($add) { $delta['+'] = array_fuse($add); }\n  if ($rem) { $delta['-'] = array_fuse($rem); }\n  return $delta;\n}","typeGuard":"function isEdgeDeltaValue($value) {\n  if (!is_array($value)) {\n    return false;\n  }\n  foreach ($value as $key => $ignored) {\n    if (!in_array($key, array('+', '-', '='), true)) {\n      return false;\n    }\n  }\n  return true;\n}","tryCatchPattern":"try {\n  $editor->applyTransactions($object, $xactions);\n} catch (Exception $ex) {\n  if (preg_match('/Invalid \\'new\\' value for Edge transaction/', $ex->getMessage())) {\n    // Reformat value as a +/-/= delta and retry once\n  }\n  throw $ex;\n}","preventionTips":["Treat edge transaction values as delta dicts from the start; use array_fuge/array_fuse for key=value lists.","Pin the 'edge:type' metadata when constructing the transaction and never override 'type' in specs.","Add integration tests over applyTransactions() for custom edge workflows."],"tags":["phabricator","transactions","edges","validation","php"],"backgroundTag":"transaction-validation-failed","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}