{"record":{"id":"3ab6bbfbff7d61f2","repo":"phacility/phabricator","slug":"specify-exactly-one-of-s-and-s","errorCode":null,"errorMessage":"Specify exactly one of '%s' and '%s'.","messagePattern":"Specify exactly one of '(.+?)' and '(.+?)'\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/maniphest/conduit/ManiphestUpdateConduitAPIMethod.php","lineNumber":44,"sourceCode":"      'ERR-INVALID-PARAMETER' => pht('Missing or malformed parameter.'),\n      'ERR-NO-EFFECT'         => pht('Update has no effect.'),\n    );\n  }\n\n  protected function defineParamTypes() {\n    return $this->getTaskFields($is_new = false);\n  }\n\n  protected function defineReturnType() {\n    return 'nonempty dict';\n  }\n\n  protected function execute(ConduitAPIRequest $request) {\n    $id = $request->getValue('id');\n    $phid = $request->getValue('phid');\n\n    if (($id && $phid) || (!$id && !$phid)) {\n      throw new Exception(\n        pht(\n          \"Specify exactly one of '%s' and '%s'.\",\n          'id',\n          'phid'));\n    }\n\n    $query = id(new ManiphestTaskQuery())\n      ->setViewer($request->getUser())\n      ->needSubscriberPHIDs(true)\n      ->needProjectPHIDs(true);\n    if ($id) {\n      $query->withIDs(array($id));\n    } else {\n      $query->withPHIDs(array($phid));\n    }\n    $task = $query->executeOne();\n\n    $params = $request->getAllParameters();","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/maniphest/conduit/ManiphestUpdateConduitAPIMethod.php#L26-L62","documentation":"The frozen Conduit method 'maniphest.update' requires the caller to identify the target task with exactly one of the parameters 'id' or 'phid'. The guard in execute() throws a plain Exception when both are supplied at once or when neither is, because the method cannot decide which task to load.","triggerScenarios":"Calling maniphest.update with both 'id' and 'phid' set (id && phid), or with neither set (!$id && !$phid). Example bad payloads: array('id' => 123, 'phid' => 'PHID-TASK-...', 'title' => 'x') or array('title' => 'x') with no identifier at all.","commonSituations":"Wrapper scripts that build a params dict and unconditionally merge in both identifiers 'to be safe', or code paths where the id/phid variable is empty due to an upstream lookup failure (e.g. the task was looked up by a previous call that returned nothing). Copy-pasting a maniphest.create response (which returns a phid) into an update template that already has an id field.","solutions":["Pass exactly one identifier: use 'id' => $task_id or 'phid' => $task_phid, never both.","If the identifier came from a failed lookup, fix the upstream lookup so id/phid is always a real non-empty value before calling update.","Long term, migrate to maniphest.edit, which takes a single 'object' identifier and replaces this frozen method."],"exampleFix":"// before\n$params = array(\n  'id'   => $task_id,\n  'phid' => $task_phid, // both set -> throws\n  'title' => 'New title',\n);\n\n// after\n$params = array(\n  'phid' => $task_phid,\n  'title' => 'New title',\n);","handlingStrategy":"validation","validationCode":"$has_id  = !empty($params['id']);\n$has_phid = !empty($params['phid']);\nif ($has_id === $has_phid) { // both or neither\n  throw new InvalidArgumentException(\n    'Pass exactly one of id or phid to maniphest.update'\n  );\n}","typeGuard":null,"tryCatchPattern":"try {\n  $result = $conduit->callMethodSynchronous('maniphest.update', $params);\n} catch (Exception $e) {\n  if (strpos($e->getMessage(), \"exactly one of 'id' and 'phid'\") !== false) {\n    // fix caller-supplied identifier and retry once\n  } else {\n    throw $e;\n  }\n}","preventionTips":["Build the identifier from a single source of truth (id XOR phid), never merge both.","Fail fast in wrappers when the identifier variable is empty."],"tags":["phabricator","maniphest","conduit","parameter-validation"],"backgroundTag":"mutually-exclusive-parameters","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}