{"record":{"id":"b99bcbd226ec5a65","repo":"phacility/phabricator","slug":"configured-datasource-class-s-must-be-a-valid-s","errorCode":null,"errorMessage":"Configured datasource class \"%s\" must be a valid subclass of \"%s\".","messagePattern":"Configured datasource class \"(.+?)\" must be a valid subclass of \"(.+?)\"\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldDatasource.php","lineNumber":16,"sourceCode":"<?php\n\nfinal class PhabricatorStandardCustomFieldDatasource\n  extends PhabricatorStandardCustomFieldTokenizer {\n\n  public function getFieldType() {\n    return 'datasource';\n  }\n\n  public function getDatasource() {\n    $parameters = $this->getFieldConfigValue('datasource.parameters', array());\n\n    $class = $this->getFieldConfigValue('datasource.class');\n    $parent = 'PhabricatorTypeaheadDatasource';\n    if (!is_subclass_of($class, $parent)) {\n      throw new Exception(\n        pht(\n          'Configured datasource class \"%s\" must be a valid subclass of '.\n          '\"%s\".',\n          $class,\n          $parent));\n    }\n\n    return newv($class, array())\n      ->setParameters($parameters);\n  }\n\n}\n","sourceCodeStart":1,"sourceCodeEnd":29,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldDatasource.php#L1-L29","documentation":"PhabricatorStandardCustomFieldDatasource::getDatasource() builds the typeahead datasource for a 'datasource'-type custom field from the field's 'datasource.class' configuration. Before instantiating, it verifies with is_subclass_of() that the configured class descends from PhabricatorTypeaheadDatasource; a missing, misspelled, unloaded or unrelated class name throws immediately. The error surfaces as soon as the field is rendered or its value edited (any tokenizer/datasource UI), and the two placeholders carry the configured class and the required parent.","triggerScenarios":"Defining a standard custom field with getFieldType() 'datasource' whose field config sets 'datasource.class' to something that is not a PhabricatorTypeaheadDatasource subclass — e.g. a search engine class, a plain helper class, or a typo. Also triggered when the named class lives in an extension library that is not loaded, so is_subclass_of() returns false.","commonSituations":"Copy-pasting field config between installs where class names differ; referencing an application datasource class that was renamed during a Phabricator upgrade; forgetting to register the extension library so the class never loads.","solutions":["Open the custom field's configuration and check the 'datasource.class' value; confirm it names an existing class.","Verify that class actually extends PhabricatorTypeaheadDatasource (grep its definition).","If the class is in an extension library, make sure the library is registered and its map rebuilt (arc liberate), then clear caches.","Fix the class name and re-save the configuration."],"exampleFix":"// before\n'datasource.class' => 'MyProjectTaskSearchEngine',\n\n// after\n'datasource.class' => 'MyProjectTaskDatasource',\n// MyProjectTaskDatasource extends PhabricatorTypeaheadDatasource","handlingStrategy":"validation","validationCode":"$class = idx($field_spec, 'datasource.class');\nif (!is_string($class) || !class_exists($class) || !is_subclass_of($class, 'PhabricatorTypeaheadDatasource')) {\n  // reject the field specification before it reaches the UI\n}","typeGuard":"function is_valid_datasource_class($class) {\n  return is_string($class)\n    && class_exists($class)\n    && is_subclass_of($class, 'PhabricatorTypeaheadDatasource');\n}","tryCatchPattern":null,"preventionTips":["Grep the datasource class and confirm its declaration ends in 'extends PhabricatorTypeaheadDatasource' before referencing it.","Add a config lint step that validates every 'datasource'-type custom field.","Re-validate custom field config after every Phabricator or extension library upgrade."],"tags":["phabricator","custom-fields","typeahead","datasource","php","configuration"],"backgroundTag":"invalid-class-configuration","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}