phacility/phabricator · error · Exception
Custom field class "%s" does not exist.
Error message
Custom field class "%s" does not exist.
What it means
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.
Source
Thrown at src/infrastructure/customfield/datasource/PhabricatorStandardSelectCustomFieldDatasource.php:23
public function getBrowseTitle() {
return pht('Browse Values');
}
public function getPlaceholderText() {
return pht('Type a field value...');
}
public function getDatasourceApplicationClass() {
return null;
}
public function loadResults() {
$viewer = $this->getViewer();
$class = $this->getParameter('object');
if (!class_exists($class)) {
throw new Exception(
pht(
'Custom field class "%s" does not exist.',
$class));
}
$reflection = new ReflectionClass($class);
$interface = 'PhabricatorCustomFieldInterface';
if (!$reflection->implementsInterface($interface)) {
throw new Exception(
pht(
'Custom field class "%s" does not implement interface "%s".',
$class,
$interface));
}
$role = $this->getParameter('role');
if (!strlen($role)) {
throw new Exception(pht('No custom field role specified.'));View on GitHub (pinned to 5720a38cfe)
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.
Example fix
// before
$datasource->setParameter('object', 'MyCompantTaskCustomField');
// after
$datasource->setParameter('object', 'MyCompanyTaskCustomField'); Defensive patterns
Strategy: validation
Validate before calling
$class = $datasource->getParameter('object');
if (!class_exists($class)) {
throw new Exception('object parameter must be an existing class: '.$class);
} Type guard
function isValidCustomFieldObjectClass($class) {
return is_string($class)
&& class_exists($class)
&& is_subclass_of($class, 'PhabricatorCustomFieldInterface', true);
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Custom field class "%s" does not implement interface "%s".
- No custom field role specified.
- No custom field key specified.
- No field with field key "%s" exists for objects of class "%s
- Field "%s" is not a standard select field, nor a proxy of a
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/e191235b83926805.
Report an issue: GitHub.