{"record":{"id":"2e412b4bcf36f18f","repo":"phacility/phabricator","slug":"parameter-s-is-not-a-list-of-transactions","errorCode":null,"errorMessage":"Parameter \"%s\" is not a list of transactions.","messagePattern":"Parameter \"(.+?)\" is not a list of transactions\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/transactions/editengine/PhabricatorEditEngine.php","lineNumber":2190,"sourceCode":"        'phid' => $xaction->getPHID(),\n      );\n    }\n\n    return array(\n      'object' => array(\n        'id' => (int)$object->getID(),\n        'phid' => $object->getPHID(),\n      ),\n      'transactions' => $xactions_struct,\n    );\n  }\n\n  private function getRawConduitTransactions(ConduitAPIRequest $request) {\n    $transactions_key = 'transactions';\n\n    $xactions = $request->getValue($transactions_key);\n    if (!is_array($xactions)) {\n      throw new Exception(\n        pht(\n          'Parameter \"%s\" is not a list of transactions.',\n          $transactions_key));\n    }\n\n    foreach ($xactions as $key => $xaction) {\n      if (!is_array($xaction)) {\n        throw new Exception(\n          pht(\n            'Parameter \"%s\" must contain a list of transaction descriptions, '.\n            'but item with key \"%s\" is not a dictionary.',\n            $transactions_key,\n            $key));\n      }\n\n      if (!array_key_exists('type', $xaction)) {\n        throw new Exception(\n          pht(","sourceCodeStart":2172,"sourceCodeEnd":2208,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/transactions/editengine/PhabricatorEditEngine.php#L2172-L2208","documentation":"Edit-engine Conduit methods (maniphest.edit, differential.revision.edit, ...) pass the 'transactions' parameter to getRawConduitTransactions(), which first requires it to be a PHP array. This exception fires when the client sent anything that is not a list at all — a JSON string, a number, or null (parameter omitted).","triggerScenarios":"Calling an *.edit Conduit method with transactions serialized as a string (e.g. transactions => '[{\"type\":\"title\",\"value\":\"x\"}]' instead of an actual list), sending an integer, or omitting the parameter entirely when the method requires it.","commonSituations":"Hand-built JSON bodies where json_encode was applied twice; client libraries that stringify complex params; Python callers passing a str instead of list; curl -d with manual JSON where transactions is quoted.","solutions":["Send 'transactions' as a real list of dictionaries, e.g. [{\"type\":\"title\",\"value\":\"New title\"}]","If building the request body with json_encode/json.dumps, apply it exactly once to the whole payload","Omit nothing: every edit call needs transactions (even if only a 'comment' entry)","Log the exact payload you send and confirm transactions parses to a list before dispatch"],"exampleFix":"// before: transactions double-encoded as a JSON string\n$parameters = array(\n  'objectIdentifier' => 123,\n  'transactions' => json_encode(array(array('type' => 'title', 'value' => 'x'))),\n);\n$client->callMethod('maniphest.edit', $parameters);\n// Exception: Parameter \"transactions\" is not a list of transactions.\n\n// after: pass the raw list and let the client encode the whole body once\n$parameters = array(\n  'objectIdentifier' => 123,\n  'transactions' => array(array('type' => 'title', 'value' => 'x')),\n);\n$client->callMethod('maniphest.edit', $parameters);","handlingStrategy":"validation","validationCode":"// Structural pre-flight before any *.edit call:\nfunction transactionsValid($txns) {\n  if (!is_array($txns) || $txns === array()) {\n    return false;\n  }\n  foreach ($txns as $txn) {\n    if (!is_array($txn)) { return false; }\n    if (!array_key_exists('type', $txn)) { return false; }\n    if (!array_key_exists('value', $txn)) { return false; }\n  }\n  return true;\n}\nif (!transactionsValid($parameters['transactions'])) {\n  // fix the payload locally; do not send it\n}","typeGuard":"function isConduitTransactionList($value) {\n  return is_array($value)\n    && array_filter($value, 'is_array') === $value\n    && $value === array_values($value);\n}","tryCatchPattern":"try {\n  $result = $client->callMethod('maniphest.edit', $parameters);\n} catch (ConduitClientException $ex) {\n  if (strpos($ex->getMessage(), 'is not a list of transactions') !== false) {\n    // client bug: payload serialization; fix sender, do not retry as-is\n  } else {\n    throw $ex;\n  }\n}","preventionTips":["Let the conduit client encode the whole request; never json_encode a sub-parameter yourself","Assert the transactions value is a list of dicts in your wrapper before every send","Add a payload-shape unit test to your client library"],"tags":["phabricator","conduit","request-validation","payload","php"],"backgroundTag":"invalid-request-payload","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}