{"record":{"id":"e191235b83926805","repo":"phacility/phabricator","slug":"custom-field-class-s-does-not-exist","errorCode":null,"errorMessage":"Custom field class \"%s\" does not exist.","messagePattern":"Custom field class \"(.+?)\" does not exist\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/infrastructure/customfield/datasource/PhabricatorStandardSelectCustomFieldDatasource.php","lineNumber":23,"sourceCode":"\n  public function getBrowseTitle() {\n    return pht('Browse Values');\n  }\n\n  public function getPlaceholderText() {\n    return pht('Type a field value...');\n  }\n\n  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.'));","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/infrastructure/customfield/datasource/PhabricatorStandardSelectCustomFieldDatasource.php#L5-L41","documentation":"PhabricatorStandardSelectCustomFieldDatasource::loadResults() reads the `object` parameter (a class name), expects it to name an existing class, and throws immediately when `class_exists($class)` is false. The parameter is supplied by whoever wires up the typeahead datasource, so the error indicates a wiring or naming mistake, not user input.","triggerScenarios":"Instantiating the datasource (or registering a typeahead function) with an `object` parameter that names a missing class — a typo, a class renamed between versions, or an extension that was disabled after the datasource config was written.","commonSituations":"Typeahead function definitions referencing custom field classes from an uninstalled extension; copying datasource wiring between installs where class names differ; case mismatches in namespaced class names.","solutions":["Set the `object` parameter to a fully qualified, currently existing class name (verify with a quick `class_exists()` check or `bin/dev lookup class`).","If the class came from an extension, reinstall/enable that extension.","Regenerate the datasource/function wiring after renaming a field class so the stored parameter matches."],"exampleFix":"// before\n$datasource->setParameter('object', 'MyCompantTaskCustomField');\n// after\n$datasource->setParameter('object', 'MyCompanyTaskCustomField');","handlingStrategy":"validation","validationCode":"$class = $datasource->getParameter('object');\nif (!class_exists($class)) {\n  throw new Exception('object parameter must be an existing class: '.$class);\n}","typeGuard":"function isValidCustomFieldObjectClass($class) {\n  return is_string($class)\n    && class_exists($class)\n    && is_subclass_of($class, 'PhabricatorCustomFieldInterface', true);\n}","tryCatchPattern":null,"preventionTips":["Generate datasource parameters from live class references (e.g. get_class($object)) instead of literals where possible.","Re-verify typeahead wiring after disabling an extension or renaming a custom field class.","Centralize datasource construction behind one helper so the object/role/key triple is always set together."],"tags":["php","phabricator","custom-fields","typeahead","datasource"],"backgroundTag":"custom-field-datasource-misuse","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}