{"record":{"id":"649f8ebc24aec9cc","repo":"phacility/phabricator","slug":"custom-field-class-s-does-not-implement-interfa","errorCode":null,"errorMessage":"Custom field class \"%s\" does not implement interface \"%s\".","messagePattern":"Custom field class \"(.+?)\" does not implement interface \"(.+?)\"\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/infrastructure/customfield/datasource/PhabricatorStandardSelectCustomFieldDatasource.php","lineNumber":32,"sourceCode":"  public function getDatasourceApplicationClass() {\n    return null;\n  }\n\n  public function loadResults() {\n    $viewer = $this->getViewer();\n\n    $class = $this->getParameter('object');\n    if (!class_exists($class)) {\n      throw new Exception(\n        pht(\n          'Custom field class \"%s\" does not exist.',\n          $class));\n    }\n\n    $reflection = new ReflectionClass($class);\n    $interface = 'PhabricatorCustomFieldInterface';\n    if (!$reflection->implementsInterface($interface)) {\n      throw new Exception(\n        pht(\n          'Custom field class \"%s\" does not implement interface \"%s\".',\n          $class,\n          $interface));\n    }\n\n    $role = $this->getParameter('role');\n    if (!strlen($role)) {\n      throw new Exception(pht('No custom field role specified.'));\n    }\n\n    $object = newv($class, array());\n    $field_list = PhabricatorCustomField::getObjectFields($object, $role);\n\n    $field_key = $this->getParameter('key');\n    if (!strlen($field_key)) {\n      throw new Exception(pht('No custom field key specified.'));\n    }","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/infrastructure/customfield/datasource/PhabricatorStandardSelectCustomFieldDatasource.php#L14-L50","documentation":"After confirming the `object` class exists, the datasource requires it to implement PhabricatorCustomFieldInterface (the contract that supplies custom fields for objects). ReflectionClass::implementsInterface fails and this exception is thrown for any class that does not.","triggerScenarios":"Passing a class that exists but is a plain model/DAO class (e.g. a Maniphest task DAO or a random PhabricatorPHID class) rather than the application domain class that implements PhabricatorCustomFieldInterface.","commonSituations":"Pointing `object` at the wrong class in the same family (Task vs ManiphestTask, a Form vs the object); new custom object types that forgot to implement the interface; following an example that used a different install's class names.","solutions":["Point `object` at the domain object class that implements PhabricatorCustomFieldInterface (e.g. ManiphestTask, PhabricatorUser, PHID-hosting business objects).","If it is your own class, implement PhabricatorCustomFieldInterface (getCustomFieldSpecification, getCustomFields, attachCustomFields, etc.).","Verify with `is_subclass_of($class, 'PhabricatorCustomFieldInterface', true)` before wiring."],"exampleFix":"// before\n$datasource->setParameter('object', 'ManiphestTaskDAO');\n// after\n$datasource->setParameter('object', 'ManiphestTask');","handlingStrategy":"type-guard","validationCode":"if (!in_array('PhabricatorCustomFieldInterface', class_implements($class), true)) {\n  throw new Exception($class.' must implement PhabricatorCustomFieldInterface');\n}","typeGuard":"function isValidCustomFieldObjectClass($class) {\n  return is_string($class)\n    && class_exists($class)\n    && (new ReflectionClass($class))\n        ->implementsInterface('PhabricatorCustomFieldInterface');\n}","tryCatchPattern":null,"preventionTips":["Point `object` at the application domain class (ManiphestTask, PhabricatorUser), not DAOs or helpers.","For custom object types, implement PhabricatorCustomFieldInterface early and cover it with a smoke test that builds the field list."],"tags":["php","phabricator","custom-fields","typeahead","datasource","interfaces"],"backgroundTag":"custom-field-datasource-misuse","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}