{"record":{"id":"2e9080626b8ed76d","repo":"phacility/phabricator","slug":"no-custom-field-role-specified","errorCode":null,"errorMessage":"No custom field role specified.","messagePattern":"No custom field role specified\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/infrastructure/customfield/datasource/PhabricatorStandardSelectCustomFieldDatasource.php","lineNumber":41,"sourceCode":"      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.'));\n    }\n\n    $object = newv($class, array());\n    $field_list = PhabricatorCustomField::getObjectFields($object, $role);\n\n    $field_key = $this->getParameter('key');\n    if (!strlen($field_key)) {\n      throw new Exception(pht('No custom field key specified.'));\n    }\n\n    $field = null;\n    foreach ($field_list->getFields() as $candidate_field) {\n      if ($candidate_field->getFieldKey() == $field_key) {\n        $field = $candidate_field;\n        break;\n      }\n    }\n","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/infrastructure/customfield/datasource/PhabricatorStandardSelectCustomFieldDatasource.php#L23-L59","documentation":"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.","triggerScenarios":"Wiring the datasource with only `object` and `key` parameters and never setting `role`, or setting it to an empty string / null via setParameter('role', '').","commonSituations":"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.","solutions":["Set the role parameter, e.g. `setParameter('role', PhabricatorCustomField::ROLE_EDIT)` (or the string 'edit').","Choose the role matching how the field will be used: ROLE_EDIT for edit forms, ROLE_VIEW for rendering, ROLE_DEFAULT for general use.","Audit the parameter array so `object`, `role`, and `key` are always all present."],"exampleFix":"// before\n$datasource->setParameter('object', 'ManiphestTask');\n$datasource->setParameter('key', 'std:project:foo');\n// after\n$datasource->setParameter('object', 'ManiphestTask');\n$datasource->setParameter('role', PhabricatorCustomField::ROLE_EDIT);\n$datasource->setParameter('key', 'std:project:foo');","handlingStrategy":"validation","validationCode":"foreach (array('object', 'role', 'key') as $param) {\n  if (!strlen((string)$datasource->getParameter($param))) {\n    throw new Exception('datasource parameter \"'.$param.'\" is required');\n  }\n}","typeGuard":"function hasCompleteSelectDatasourceParams($datasource) {\n  foreach (array('object', 'role', 'key') as $param) {\n    if (!strlen((string)$datasource->getParameter($param))) {\n      return false;\n    }\n  }\n  return true;\n}","tryCatchPattern":null,"preventionTips":["Use the valid-role constants (PhabricatorCustomField::ROLE_EDIT / ROLE_VIEW / ROLE_DEFAULT) rather than ad-hoc strings.","Set all three parameters in one helper call so a partial wiring cannot reach loadResults().","Add a unit test that instantiates the datasource and calls loadResults() for each configured typeahead function."],"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"}