phacility/phabricator · error · Exception

Edge transactions must have destination PHIDs as in edge lis

Error message

Edge transactions must have destination PHIDs as in edge lists (found key "%s" on transaction of type "%s").

What it means

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.

Source

Thrown at src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php:2677

        $xaction,
        $edge,
        $dst_phid);
    }

    foreach ($new_rem as $dst_phid => $edge) {
      unset($result[$dst_phid]);
    }

    return $result;
  }

  private function checkEdgeList($list, $edge_type) {
    if (!$list) {
      return;
    }
    foreach ($list as $key => $item) {
      if (phid_get_type($key) === PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN) {
        throw new Exception(
          pht(
            'Edge transactions must have destination PHIDs as in edge '.
            'lists (found key "%s" on transaction of type "%s").',
            $key,
            $edge_type));
      }
      if (!is_array($item) && $item !== $key) {
        throw new Exception(
          pht(
            'Edge transactions must have PHIDs or edge specs as values '.
            '(found value "%s" on transaction of type "%s").',
            $item,
            $edge_type));
      }
    }
  }

  private function normalizeEdgeTransactionValue(

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Resolve identifiers to PHIDs before building the transaction (e.g. PhabricatorObjectQuery with monograms, or the appropriate search endpoint).
  2. Key every edge entry by its destination PHID: array('+' => array('PHID-PROJ-...' => 'PHID-PROJ-...')).
  3. Sanitize/trim values when importing external data and log any token that does not start with 'PHID-'.

Example fix

// before
$new = array('+' => array('alice' => 'alice'));

// after
$user_phid = id(new PhabricatorPeopleUserFindEngine())
  ->setViewer($viewer)
  ->findUsers('alice'); // then use resolved PHID(s)
$new = array('+' => array($user_phid => $user_phid));
Defensive patterns

Strategy: validation

Validate before calling

// Resolve every identifier to a PHID before building the edge list
$phids = array();
foreach ($raw_identifiers as $identifier) {
  $phid = id(new PhabricatorObjectQuery())
    ->setViewer($viewer)
    ->withNames(array($identifier))
    ->executeOne();
  if (!$phid) {
    continue; // or collect an error for the user
  }
  $phids[] = $phid->getPHID();
}
$new = array('+' => array_fuse($phids));

Type guard

function isPhid($value) {
  return is_string($value)
    && preg_match('/^PHID-[A-Z]{4}-/', $value)
    && phid_get_type($value) !== PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/32cf52b633aceda0. Report an issue: GitHub.