Posted this in Drupal Paragraphs issue queue, but no response. Trying here.

Drupal core 9.4.5. Paragraphs 8.x-1.2

Every tutorial on Drupal 8/9 paragraphs migration uses the destination plugin: entity_reference_revisions:paragraph. As I understand it, the reason for this is:

This plugin is actually provided by the Entity Reference Revisions module. It is very important to note that paragraphs entities are revisioned. This means that when you want to create a reference to them, you need to provide two IDs: `target_id` and `target_revision_id`. Regular entity reference fields like files, images, and taxonomy terms only require the `target_id`.

See: https://understanddrupal.com/lessons/introduction-paragraphs-migrations-drupal/

I intend to migrate Drupal 7 book content using a custom SQL source plugin. With this method, I can provide most of the Paragraph entity field requirements, including the revision id.

My question is, could I then, in my migration yaml file, use:

destination: plugin: 'entity:paragraph'

And migrate my D7 book data directly into the D9 paragraph entity?

I can create a custom SQL source plugin that has all the node and book fields I need for each book. I have attached a sample PDF of SQL code and resulting data elements. These would be the fields returned from my source plugin: n.nid, n.vid, n.type, n.language, n.title, n.uid, n.status, n.created, n.changed, b.mlid, b.bid, ml.menu_name, ml.plid, ml.link_path, ml.module, ml.has_children, ml.depth, ml.p1, ml.p2, ml.p3, ml.p4, ml.p5, ml.p6, ml.p7, ml.p8, ml.p9

According to the Paragraph Entity definition, I can supply almost all the the required destination fields from my source output:

Paragraph entity
Module: Paragraphs module
Class: Drupal\paragraphs\Entity\Paragraph
Related article: Introduction to paragraphs migrations in Drupal

List of base field definitions:

id: (integer) ID.
uuid: (uuid) UUID.
revision_id: (integer) Revision ID.
langcode: (language) The paragraphs entity language code.
type: (entity_reference to paragraphs_type) Paragraph type.
status: (boolean) Published.
created: (created) The time that the Paragraph was created.
parent_id: (string) The ID of the parent entity of which this entity is referenced.
parent_type: (string) The entity parent type to which this entity is referenced.
parent_field_name: (string) The entity parent field name to which this entity is referenced.
behavior_settings: (string_long) The behavior plugin settings
default_langcode: (boolean) A flag indicating whether this is the default translation.
revision_default: (boolean) A flag indicating whether this was a default revision when it was saved.
revision_translation_affected: (boolean) Indicates if the last edit of a translation belongs to current revision.
workspace: (entity_reference to workspace) Indicates the workspace that this revision belongs to.
List of field storage configurations:

field_reusable_paragraph: entity_reference field.

The process and destination sections of my YAML migration file would then look something like this:

    id: nid
        UUID: (unknown)
    revision_id: vid (this is the book node's revision id)
    langcode: (either language or default to 'en')
    type: (default to 'agenda_section')
    status: status
    created: created
    parent_id: (have to figure out how to get nid of plid) 
    parent_type: ('node' or 'paragraph') 
    parent_field_name: (default to 'field_body1' or 'field_body2' depending on whether parent is node or paragraph)
    behavior_settings: (unknown) 
    default_langcode: (default 'true') 
    revision_default: (default 'true') 
    revision_translation_affected: (unknown) 
    workspace: (unknown) 
  plugin: 'entity:paragraph'
  default_bundle: agenda_section
  migration_dependencies: null

I would need more information on UUID, behavior_settings, revision_translation_affected and workspace to determine what should go there. If I can safely leave them blank, all the better.

I would probably have to run a separate migrations for:

  1. The top level nodes (which would migrate as nodes)
  2. First level Paragraphs (parent is always node)
  3. Level 1+ Paragraphs (parent is always paragraph)

I do not know if it is possible to migrate directly into paragraph entity. But if it isn't, it would be nice if we could. Most of the paragraph entity fields are listed in the Drupal database paragraph tables:

select pi.id, pi.revision_id, pi.type, pifd.parent_id, pifd.parent_type, pifd.parent_field_name, pfd.field_content_value, pfd.field_content_format, pfd.bundle, pifd.status, pifd.langcode, pi.uuid, pifd.created, pifd.default_langcode, pifd.behavior_settings, pifd.revision_translation_affected from paragraphs_item pi inner join paragraphs_item_field_data pifd on pi.id = pifd.id inner join paragraph__field_content pfd on pi.id = pfd.entity_id

  • id
  • revision_id
  • type
  • parent_id
  • parent_type
  • parent_field_name
  • field_content_value
  • field_content_format
  • bundle
  • status
  • langcode
  • uuid
  • created
  • default_langcode
  • behavior_settings
  • revision_translation_affected
So, theoretically, I should be able to write a program that simply inserts the source values into the destination fields in the appropriate destination tables. But, in doing so, I lose the migration "rollback" feature. So, I would prefer to do this within the migration framework.

Instead of only being able to migrate paragraphs into entity_reference_revisions:paragraph, we have option to migrate into entity:paragraph. This gives more flexibility when migrating from various sources (other than Drupal database).

  • just wanted to know how will you use created paragraph data? Unless they are attached to some other entity like node you wont be able to render them on frontend right? Commented Sep 21, 2022 at 8:49
  • If you still want to create paragraphs alone you can do it by custom process plugin from here just return empty array and attach it to dummy field which you can delete once paragraphs are created drupal.stackexchange.com/a/304157/71454 Commented Sep 21, 2022 at 8:56
  • >I should be able to write a program that simply inserts the source values into the destination fields in the appropriate destination tables. Never ever do that in Drupal, you are bypassing many APIs. Commented Sep 21, 2022 at 8:57
  • There are two paragraph entity fields I can supply: parent_id: (string) The ID of the parent entity of which this entity is referenced. parent_type: (string) The entity parent type to which this entity is referenced. Some paragraphs will be attached to nodes. Some will be attached to other paragraphs, which are then attached to nodes. Commented Sep 21, 2022 at 9:03
  • My hope was that I could use destination: plugin: entity:paragraph instead of destination: plugin: 'entity_reference_revisions:paragraph'. But it's beginning to look like that is not possible. The biggest issue will be how to migrate a nested hierarchy of paragraphs. Commented Sep 21, 2022 at 9:07

1 Answer 1


No, it is not possible.

Paragraphs can only be migrated using plugin: entity_reference_revisions:paragraph at this time.

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.