phacility/phabricator · error · Exception

No custom field role specified.

Error message

No custom field role specified.

What it means

The datasource requires a `role` parameter (e.g. PhabricatorCustomField::ROLE_EDIT, ROLE_VIEW, ROLE_DEFAULT) that selects which field list to build via PhabricatorCustomField::getObjectFields(). If the parameter is absent or an empty string, loadResults throws before doing any work.

Source

Thrown at src/infrastructure/customfield/datasource/PhabricatorStandardSelectCustomFieldDatasource.php:41

      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.'));
    }

    $object = newv($class, array());
    $field_list = PhabricatorCustomField::getObjectFields($object, $role);

    $field_key = $this->getParameter('key');
    if (!strlen($field_key)) {
      throw new Exception(pht('No custom field key specified.'));
    }

    $field = null;
    foreach ($field_list->getFields() as $candidate_field) {
      if ($candidate_field->getFieldKey() == $field_key) {
        $field = $candidate_field;
        break;
      }
    }

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Set the role parameter, e.g. `setParameter('role', PhabricatorCustomField::ROLE_EDIT)` (or the string 'edit').
  2. Choose the role matching how the field will be used: ROLE_EDIT for edit forms, ROLE_VIEW for rendering, ROLE_DEFAULT for general use.
  3. Audit the parameter array so `object`, `role`, and `key` are always all present.

Example fix

// before
$datasource->setParameter('object', 'ManiphestTask');
$datasource->setParameter('key', 'std:project:foo');
// after
$datasource->setParameter('object', 'ManiphestTask');
$datasource->setParameter('role', PhabricatorCustomField::ROLE_EDIT);
$datasource->setParameter('key', 'std:project:foo');
Defensive patterns

Strategy: validation

Validate before calling

foreach (array('object', 'role', 'key') as $param) {
  if (!strlen((string)$datasource->getParameter($param))) {
    throw new Exception('datasource parameter "'.$param.'" is required');
  }
}

Type guard

function hasCompleteSelectDatasourceParams($datasource) {
  foreach (array('object', 'role', 'key') as $param) {
    if (!strlen((string)$datasource->getParameter($param))) {
      return false;
    }
  }
  return true;
}

Prevention

When it happens

Trigger: Wiring the datasource with only `object` and `key` parameters and never setting `role`, or setting it to an empty string / null via setParameter('role', '').

Common situations: Copying datasource wiring from an example that omitted the role; conditionally setting parameters and skipping `role` on one path; building the parameter list dynamically and the role key gets dropped.

Related errors


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