{"record":{"id":"abd673753b644e27","repo":"phacility/phabricator","slug":"constraint-phids-to-transaction-search-require","errorCode":null,"errorMessage":"Constraint \"phids\" to \"transaction.search\" requires nonempty list, empty list provided.","messagePattern":"Constraint \"phids\" to \"transaction\\.search\" requires nonempty list, empty list provided\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/transactions/conduit/TransactionSearchConduitAPIMethod.php","lineNumber":306,"sourceCode":"\n    return $this->addPagerResults($results, $pager);\n  }\n\n  private function applyConstraints(\n    array $constraints,\n    PhabricatorApplicationTransactionQuery $query) {\n\n    PhutilTypeSpec::checkMap(\n      $constraints,\n      array(\n        'phids' => 'optional list<string>',\n        'authorPHIDs' => 'optional list<string>',\n      ));\n\n    $with_phids = idx($constraints, 'phids');\n\n    if ($with_phids === array()) {\n      throw new Exception(\n        pht(\n          'Constraint \"phids\" to \"transaction.search\" requires nonempty list, '.\n          'empty list provided.'));\n    }\n\n    if ($with_phids) {\n      $query->withPHIDs($with_phids);\n    }\n\n    $with_authors = idx($constraints, 'authorPHIDs');\n    if ($with_authors === array()) {\n      throw new Exception(\n        pht(\n          'Constraint \"authorPHIDs\" to \"transaction.search\" requires '.\n          'nonempty list, empty list provided.'));\n    }\n\n    if ($with_authors) {","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/transactions/conduit/TransactionSearchConduitAPIMethod.php#L288-L324","documentation":"In the transaction.search Conduit method, constraints.phids is typed 'optional list<string>', but an explicitly empty list is meaningless for an IN-style filter and is rejected with a plain Exception. idx() distinguishes null (key absent) from array() (present but empty), so only the explicit empty-array case throws. Omit the key entirely when there is no PHID constraint.","triggerScenarios":"Calling transaction.search with constraints: {\"phids\": []} — typically a client that always includes the field and serializes its own empty filter list.","commonSituations":"Generated API clients (arc call-conduit, Python/JS wrappers) that serialize empty arrays instead of dropping the key; UI code forwarding an empty multi-select as an empty list.","solutions":["Build the constraints map conditionally: only set phids when the list is nonempty.","Pass at least one real PHID if you genuinely want the filter.","Fix client helper code that merges empty defaults into request payloads."],"exampleFix":"// before\n$params = array('constraints' => array('phids' => $phids));\n// after\n$params = array('constraints' => array());\nif ($phids) {\n  $params['constraints']['phids'] = $phids;\n}","handlingStrategy":"validation","validationCode":"// strip empty constraint lists before the conduit call\n$constraints = array();\nif ($phids) {\n  $constraints['phids'] = $phids;\n}\n$parameters = array('constraints' => $constraints);","typeGuard":"// PHP: only nonempty string lists may be sent as phids\nfunction isValidPhidList($value) {\n  return $value === null\n    || (is_array($value) && count($value) > 0\n        && !in_array('', $value, true));\n}","tryCatchPattern":"Catch the conduit error client-side, detect 'requires nonempty list' with the constraint name in the message, then re-send once with empty-list constraints removed — this is safe because the error is raised before any query executes.","preventionTips":["Never serialize empty arrays into constraints; drop the key instead.","Centralize constraint building in one helper that filters empty lists."],"tags":["phabricator","conduit","transaction-search","api"],"backgroundTag":"api-parameter-validation","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}