entity_get_form_display setComponent throws "plugin does not exist" regardless of type 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' =&gt; 'field_phone',
  'entity_type' =&gt; 'contact',
  'type' =&gt; 'string',
  'translatable' =&gt; false,
];
$field_values = [
  'field_name' =&gt; 'field_phone',
  'entity_type' =&gt; 'contact',
  'bundle' =&gt; 'organization',
  'label' =&gt; 'Phone',
  'translatable' =&gt; false,
];
$this-&gt;entityManager-&gt;getStorage('field_storage_config')
    -&gt;create($field_storage_values)-&gt;save();
$this-&gt;entityManager-&gt;getStorage('field_config')
    -&gt;create($field_values)-&gt;save();

entity_get_form_display('contact', 'organization', 'default')
  -&gt;setComponent('field_phone', ['type' =&gt; 'string_textfield'])
  -&gt;save();
entity_get_display('contact', 'organization', 'default')
  -&gt;setComponent('field_phone', ['type' =&gt; 'string_textfield'])
  -&gt;save();


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()-&gt;setComponent()-&gt;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' =&gt; 'string_textfield' and 'type' =&gt; '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.
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')
  -&gt;setComponent('field_phone', ['type' =&gt; 'text_textfield'])
  -&gt;save();
entity_get_display('contact', 'organization', 'default')
  -&gt;setComponent('field_phone', ['type' =&gt; 'string'])
  -&gt;save();


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:

$fields['name']-&gt;setSettings([
    'default_value' =&gt; '',
    'max_length' =&gt; 255,
    'text_processing' =&gt; 0,
  ])
  -&gt;setDisplayOptions('view', ['label' =&gt; 'above', 'type' =&gt; 'string'])
  -&gt;setDisplayOptions('form', ['type' =&gt; 'text_textfield'])
  -&gt;setDisplayConfigurable('form', TRUE)
  -&gt;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:

entity_get_*display(...)-&gt;setComponent(...)


the return value is $this i.e. the display object. So chaining -&gt;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.