phacility/phabricator · error · Exception

Configured datasource class "%s" must be a valid subclass of

Error message

Configured datasource class "%s" must be a valid subclass of "%s".

What it means

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.

Source

Thrown at src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldDatasource.php:16

<?php

final class PhabricatorStandardCustomFieldDatasource
  extends PhabricatorStandardCustomFieldTokenizer {

  public function getFieldType() {
    return 'datasource';
  }

  public function getDatasource() {
    $parameters = $this->getFieldConfigValue('datasource.parameters', array());

    $class = $this->getFieldConfigValue('datasource.class');
    $parent = 'PhabricatorTypeaheadDatasource';
    if (!is_subclass_of($class, $parent)) {
      throw new Exception(
        pht(
          'Configured datasource class "%s" must be a valid subclass of '.
          '"%s".',
          $class,
          $parent));
    }

    return newv($class, array())
      ->setParameters($parameters);
  }

}

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Open the custom field's configuration and check the 'datasource.class' value; confirm it names an existing class.
  2. Verify that class actually extends PhabricatorTypeaheadDatasource (grep its definition).
  3. If the class is in an extension library, make sure the library is registered and its map rebuilt (arc liberate), then clear caches.
  4. Fix the class name and re-save the configuration.

Example fix

// before
'datasource.class' => 'MyProjectTaskSearchEngine',

// after
'datasource.class' => 'MyProjectTaskDatasource',
// MyProjectTaskDatasource extends PhabricatorTypeaheadDatasource
Defensive patterns

Strategy: validation

Validate before calling

$class = idx($field_spec, 'datasource.class');
if (!is_string($class) || !class_exists($class) || !is_subclass_of($class, 'PhabricatorTypeaheadDatasource')) {
  // reject the field specification before it reaches the UI
}

Type guard

function is_valid_datasource_class($class) {
  return is_string($class)
    && class_exists($class)
    && is_subclass_of($class, 'PhabricatorTypeaheadDatasource');
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/b99bcbd226ec5a65. Report an issue: GitHub.