I'm trying to programmatically add a field to a custom bundle, and have it appear on the custom entity type. I'm using a BaseForm extended class, and have acquired an entityManager elsewhere using dependency injection.

Below is the submitForm() code I modelled, on how FieldStorageAddForm::configureEntityFormDisplay() etc. works:

$field_storage_values = [
  'field_name' => 'field_phone',
  'entity_type' => 'contact',
  'type' => 'string',
  'translatable' => false,
$field_values = [
  'field_name' => 'field_phone',
  'entity_type' => 'contact',
  'bundle' => 'organization',
  'label' => 'Phone',
  'translatable' => false,

entity_get_form_display('contact', 'organization', 'default')
  ->setComponent('field_phone', ['type' => 'string_textfield'])
entity_get_display('contact', 'organization', 'default')
  ->setComponent('field_phone', ['type' => 'string_textfield'])

This works fine for adding the field storage, and for associating the field instance with the bundle.

However, when it gets to the entity_get_form_display()->setComponent()->save(), the following exception is thrown:

Uncaught PHP Exception Drupal\\Component\\Plugin\\Exception\\PluginNotFoundException: "The "string_string_textfield" plugin does not exist."
at /var/www/web/core/lib/Drupal/Component/Plugin/Discovery/DiscoveryTrait.php line 60

What's strange is that the same exception, quoting 'string', is seen for both 'type' => 'string_textfield' and 'type' => 'text_text_with_summary' (which doesn't even contain the word 'string'!) On the other hand, a nonsense value (e.g. 'string_string_textfield' or 'stringz_textfield') yields the exception with the nonsense value in full, no parsing. So there's some kind of detection/lookup going on, but it still can't find the relevant plugin.

What am I missing? What should the value of 'type' be? I'm aware of e.g. https://drupal.stackexchange.com/questions/177913/the-string-plugin-does-not-exist but as you can see the value suggested there doesn't seem to work in this situation.

  • Query from #drupal IRC: replace "'type' => 'string'" in the field storage configuration? This results in "Attempt to create a field storage of unknown type textfield."
    – J-P
    Commented Oct 17, 2016 at 15:10

1 Answer 1


OK, I've dug around and I think I've got a fix for this myself.

The first thing is to fix the code above; the two 'type' entries SHOULD be different, and should match values available in the dropdowns in the admin UI:

entity_get_form_display('contact', 'organization', 'default')
  ->setComponent('field_phone', ['type' => 'text_textfield'])
entity_get_display('contact', 'organization', 'default')
  ->setComponent('field_phone', ['type' => 'string'])

The second thing is that the entity's baseFieldDefinitions() were also defining a 'view' formatter type and a 'form' formatter type, but for an undeletable base field:

    'default_value' => '',
    'max_length' => 255,
    'text_processing' => 0,
  ->setDisplayOptions('view', ['label' => 'above', 'type' => 'string'])
  ->setDisplayOptions('form', ['type' => 'text_textfield'])
  ->setDisplayConfigurable('form', TRUE)
  ->setDisplayConfigurable('view', TRUE);

Originally, the form display here was also 'string'. This is obviously nothing to do with the programmatic field adding itself, but when you run:


the return value is $this i.e. the display object. So chaining ->save() causes the ENTIRE display to be saved: including base fields. Only at this point did the broken configuration in the base fields suddenly cause a problem.

But, ensuring that:

  • the 'type' for form display ALWAYS matched a value available in the admin UI for content types
  • and similar for view display
  • and ensuring this across both the new field AND base fields

fixed the original problem. Phew.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.