{"record":{"id":"77253b67a7e56be6","repo":"phacility/phabricator","slug":"object-is-of-wrong-type-for-adapter","errorCode":null,"errorMessage":"Object is of wrong type for adapter!","messagePattern":"Object is of wrong type for adapter!","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/herald/controller/HeraldRuleController.php","lineNumber":91,"sourceCode":"\n      if ($rule->isObjectRule()) {\n        $rule->setTriggerObjectPHID($request->getStr('targetPHID'));\n        $object = id(new PhabricatorObjectQuery())\n          ->setViewer($viewer)\n          ->withPHIDs(array($rule->getTriggerObjectPHID()))\n          ->requireCapabilities(\n            array(\n              PhabricatorPolicyCapability::CAN_VIEW,\n              PhabricatorPolicyCapability::CAN_EDIT,\n            ))\n          ->executeOne();\n        if (!$object) {\n          throw new Exception(\n            pht('No valid object provided for object rule!'));\n        }\n\n        if (!$adapter->canTriggerOnObject($object)) {\n          throw new Exception(\n            pht('Object is of wrong type for adapter!'));\n        }\n      }\n\n      $cancel_uri = $this->getApplicationURI();\n    }\n\n    if ($rule->isGlobalRule()) {\n      $this->requireApplicationCapability(\n        HeraldManageGlobalRulesCapability::CAPABILITY);\n    }\n\n    $adapter = HeraldAdapter::getAdapterForContentType($rule->getContentType());\n\n    $local_version = id(new HeraldRule())->getConfigVersion();\n    if ($rule->getConfigVersion() > $local_version) {\n      throw new Exception(\n        pht(","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/herald/controller/HeraldRuleController.php#L73-L109","documentation":"Thrown by HeraldRuleController for object-bound rules after the target object loaded successfully: the selected adapter's canTriggerOnObject($object) returned false. Each Herald adapter declares which object types it can attach to (via isTestAdapterForObject/canTriggerOnObject in HeraldAdapter.php:275), so this error means the rule's content type (adapter) does not accept the provided object's concrete class.","triggerScenarios":"Creating an object rule where the chosen adapter/content type disagrees with the target: e.g. an adapter selected for Differential revisions combined with a Maniphest task PHID as targetPHID, or any custom object type the adapter's canTriggerOnObject() does not whitelist.","commonSituations":"UI state gets out of sync when the user changes the adapter dropdown after choosing an object, or scripts POST a content-type/target combination that the UI would never produce. Custom applications adding new object types without updating the adapter's canTriggerOnObject() implementation.","solutions":["Match the adapter/content type to the object: pick the 'X rules' adapter that corresponds to the object you are targeting (task adapter for tasks, revision adapter for revisions).","Re-select the target object AFTER choosing the rule type in the editor so the form submits a consistent pair.","If you develop a custom adapter, extend canTriggerOnObject()/isTestAdapterForObject() to return true for your object class."],"exampleFix":"// before — mismatched pair submitted\ncontent type: differential.revision\ntargetPHID:  PHID-TASK-xxxx (a Maniphest task)\n\n// after\ncontent type: maniphest.task\ntargetPHID:  PHID-TASK-xxxx","handlingStrategy":"validation","validationCode":"// Verify adapter/object compatibility before submitting the save\n$adapter = HeraldAdapter::getAdapterForContentType($content_type);\nif (!$adapter->canTriggerOnObject($object)) {\n  return pht('This rule type cannot trigger on that object.');\n}","typeGuard":"function adapterAcceptsObject($content_type, $object) {\n  $adapter = HeraldAdapter::getAdapterForContentType($content_type);\n  return $adapter && $adapter->canTriggerOnObject($object);\n}","tryCatchPattern":"try {\n  // object-rule save path\n} catch (Exception $ex) {\n  if (strpos($ex->getMessage(), 'wrong type for adapter') !== false) {\n    // prompt user to re-pick adapter or object so the pair is consistent\n  }\n}","preventionTips":["In custom UIs/scripts, re-run canTriggerOnObject() after EITHER the adapter or the target changes, not just once.","Derive the content type from the chosen object instead of accepting it as an independent parameter."],"tags":["herald","phabricator","php","adapter","type-mismatch","object-rule"],"backgroundTag":"object-type-mismatch","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}