Known issues when upgrading from Drupal 6 or 7

Last updated on
28 November 2022

The following is a list of various items that may require special attention when migrating.

Drupal 6 or 7 source site

Potential ID conflicts

The problem

As described on the preparing an upgrade page, the destination site should be completely empty when the upgrade process is performed. The migration process preserves the IDs of the source site when importing them into the destination site. If the content has been created on the destination site before the upgrade (e.g. node with nid 1), it is likely that the IDs will conflict.

The user is warned of potential ID conflicts than can choose to continue with the upgrade or not. Site administrators should carefully consider potential conflicts. If ID conflicts are not treated with care, content or other entity items such as taxonomy terms and files can be overwritten causing data loss. It is also possible that the referencing entities are damaged, for example, content can be associated with an incorrect taxonomy term.

Scenarios that might lead to ID conflicts

  • The destination site had already been in use at the time of the upgrade and content had already been created.
  • The initial migration was completed. After the initial migration content or other entities were created in both the source and the destination sites. When the updated / newly created content was migrated from the source site, the IDs may conflict with the content that was created in the destination site.
  • The destination was in a clean state but contributed or custom modules might have added data for their own use when they were enabled in the destination site. For example, since Drupal 8 the Forum module creates a taxonomy term for its General Discussion category and that will normally get ID #1 in a fresh install. If the source data contains a taxonomy term with ID 1, it will overwrite the name of the forum's General Discussion category.
  • The source might have data that do not come with an ID, but the destination requires them to have an ID. For example, Drupal 6 handles user pictures as unmanaged files without an ID but the destination requires them to have an ID. Managed file fields with IDs will be created during the migration and these may conflict with files that are yet to be migrated.
  • Possible ID conflicts with translations are not automatically detected.
    • If you are executing a complete upgrade at once and you are performing the upgrade to an empty destination site, everything should be OK.
    • If you are executing a partial migration after an initial upgrade AND you have added translations on your destination site before migrating the updated / newly created content, the second migration may overwrite the translation made on the destination site.

Solutions

Custom migration for the conflicting items

It is possible to customize the migration for the problematic content so that new IDs are created for the problematic items. Note that this will affect their internal path and possibly their public URLs. Special care should be taken to correct any references to the changed entities.

Manipulate auto-increment values

When the destination does not have any conflicting data but the migration process may generate conflicts, it is possible to manipulate the AUTO_INCREMENT value on the destination database tables so that the IDs of the created entities do not fall within the range of other migrated entities. The migration of user pictures described above is an example of this.

Accept that data may be overwritten

It is always possible to go ahead with performing the migration. This is probably not the desired solution in many cases as it may lead to data loss.

Statistics

The access log settings and non-i18n statistics data are migrated. Consolidation of i18n statistics data are migrated as of Drupal 8.5.2. See #2930101: i18n / statistics - node counter not updated for translations.

Views

Views are not migrated, you will need to create the views in the destination site manually. For further details, please refer to #2500547: Upgrade path for Views from Drupal 6 and 7. Note that the Views Migration and Views migration from Drupal 6 or 7 modules exist to make a "best-effort" attempt, but results will need testing, particularly with more advanced views.

Drupal 6 source site

Aggregator Categories

Since Drupal 8, Drupal no longer has the concept of aggregator categories and therefore they're not migrated.

Allowed protocols

Since Drupal 8 the protocols in the "filter_protocols" are stored as a container parameter, so in case you had changed the variable "filter_allowed_protocols", enter it into your services.yml file.

Allowed vocabularies of taxonomy term reference field

In Drupal 6, the list of applicable content types for a given vocabulary is defined in vocabulary settings.  As of Drupal 8, the allowed vocabularies can be defined on taxonomy term reference field settings. This setting is currently not migrated, allowing all vocabularies to be referenced in destination site. See #3042533: D6 taxonomy term fields are not migrated with allowed vocabularies. You can manually edit the taxonomy term reference field settings in the destination site after the upgrade and select the allowed vocabulary.   

Fields missing on the edit form or the view page

One other thing that may be a point of confusion is when you run a migration that seems to be successful but afterward, you don't see your fields on the edit form. Go to the Content Types administration page and check the Manage Form Display tab for each content type. The fields added by the upgrade may be hidden on the edit form. If so, drag them up to be visible. Similarly, if they don't appear in the node view, the fields added by Migrate may have gotten hidden on the Manage Display tab and you may need to make them visible there. In migrating custom fields on an entity, the Migrate Plus module could help.

Homepage loads and the theme is broken

When running migrations, sometimes the page is white and only loads a few items. Basically, it looks like a broken theme. Visiting /user and returning to the home page normally resolves it.

Menu UI

The menu_primary_links_source and menu_secondary_links_source variables are not migrated, because they do not have counterparts in Drupal 8+.

Modules and themes

Before starting the migration, new modules and themes should be enabled, as well as the admin theme (if there is one) set.

Node content types

The default configuration in Drupal 6 has Story and Page content types. In Drupal 8+ the default content types are called Article and Basic Page (which has a machine name 'page' just like in Drupal 6).

  • Migration will map the Drupal 6 Page to  Page content type because the machine names of these content types match.
  • Migration will create the Story content type in the destination site. You might want to delete the  Drupal 8+ Article content type if you don't need it. For further details, please refer to #2236289: Migrating "story" nodes from D6 creates new content type in D8.

Profile categories

Fields grouped by the Profile module in Drupal 6 will not be grouped in Drupal 8+.

Profile field (list selection)

The "allowed values" setting of the resulting field in the destination will be a combination of all selected user values and the currently allowed values in Drupal 6 and not just the allowed values in Drupal 6.

Text/Input formats

Filter formats not recognized by the destination site will be migrated as filter_null, a filter that simply returns an empty string. This means that any Input format using an unknown filter format won't display fields' content, although the content is in the database. It may be confusing. See #2618332: Better handle replacement of missing filters with filter_null and #2630578: Formats duplicated in D6 upgrade regarding ways to improve this.

Filter formats not recognized include the infamous PHP code filter, and any other filter provided by a contrib module that is not available in your destination site..

The PHP filter is not supported in Drupal 8+—it's very bad practice, but you can use the PHP module for that if you really must.

To repair this situation, you have several alternatives:

  • Check if the modules providing the filters have a Drupal 8+ version and install them
  • Edit and save the affected input formats. This will remove the reference to format_null, and the contents will start showing. Note that since the original filter doesn't exist, contents are not being filtered and unreplaced tokens may be shown, or even the site can be exposed to any security issue
  • Edit the contents and change to another input format. This suffers the same problems as the previous point

Time Zones and Dates

Drupal 6 uses a time zone offset to compute local time. Drupal 7+ or higher use a time zone name. Unfortunately, the PHP function timezone_name_from_abbr() which converts the offset to time zone names will produce different time zone names depending upon whether or not daylight savings time is turned on or not on your server. For example, the time offset of 3600 converts to Europe/Paris if daylight saving time is off and Europe/London if the daylight saving time is on. The migration is set to ignore daylight saving time.

In time zones that use Daylight Saving Time, a date could be interpreted differently by Drupal 8+ compared with Drupal 6. For example, if the time is around midnight, the date could be seen as a different day. This causes problems especially if date tokens are used to build paths (e.g. URL aliases, file field paths). Two possible solutions are shown in #2926421: Handle date inconsistencies between D6 and D8.

URL Aliases

When migrating URL aliases for a language that is not enabled on the destination site, none of the aliases will work until you enable the language on the destination site.

Who's online block

The User activity settings are not migrated. This needs to be manually edited in the relevant View under filters/access (#2169327: Migrate the User Activity block setting).

Drupal 7 source site

Blocked IPs

The IP address is migrated. However, the id column from Drupal 7's ban_ip table is not migrated and because of this every IP address migrated will produce a notice message, [notice] New object was not saved, no error provided and it is not possible to roll back the migration.

Comment types

Drupal 7 allows the comments to have different fields on different content types. Typically the comments have Author, Subject and Comment body fields. Because the different Drupal 7 comments can have different fields, the migrations will create separate comment types for each content type:

  • Content type Foo will have a comment type comment_node_foo
  • Content type Bar will have a comment type comment_node_bar

The only exception to this is Forum comments. When the Forum module is enabled, comment type comment_forum is automatically created. The D7 Forum comments are migrated to this comment type.

Important note: Drupal 8+ Standard installation profile and Article content type

If your destination site was installed using the Standard installation profile you will have a content type called Article.

  • This content type will come with a comment field called "comment".
  • The migration system can not assume that the destination site was installed using the Standard installation profile. Therefore a comment type comment_node_article will be created and comments of the D7 Article content type will be migrated to this comment type.

As a result, your Article content type will now have two comment fields:

  • comment which came from Drupal 8+ Standard installation profile and is not used
  • comment_node_article which the migration system created

You most probably don't want to have two comment fields on the Article content type so you need to manually delete the comment comment field from Article (admin/structure/types/manage/article/fields). After you've done this, you may also want to delete the comment comment type (admin/structure/comment) if you're not using the comment comment type anywhere else.

It is recommended that the unnecessary comment field is removed from the Article content type before running the migrations because Drupal 8+ currently has a bug related to comment field deletion, see #2906470: Orphan comments and entries in comment_entity_statistics after comment field instance has been deleted.

Entity Translation

Some Drupal 7 sites using the Entity Translation module will not have the entity_translation_revision table needed to successfully migrate. This can be resolved by running on the source site the updates (entity_translation_update_*()) added by #2402247: [UNSUPPORTED] Migrate translation for enable revision. More information is available in #2396103: [DATA LOSS] Translations deleted.

Field Collection

  • Deprecated in Drupal 8, use Paragraphs module instead.
  • To migrate the Field Collection fields and data to Paragraphs when upgrading from Drupal 7 to 9, make sure Field Collection to Paragraphs module is installed beforehand.

PHP Code

Filter formats not recognized will be migrated as filter_null, a filter that simply returns an empty string. This means that any Input format using an unknown filter format won't display fields' content, although the content is in the database. It may be confusing. See #2618332: Better handle replacement of missing filters with filter_null and #2630578: Formats duplicated in D6 upgrade regarding ways to improve this.

Filter formats not recognized include the infamous PHP code filter, and any other filter provided by a contrib module that is not available in your Drupal 8+ installation.

The PHP filter is not supported in Drupal 8 + —it's very bad practice, but you can use the PHP module for that if you really must.

To repair this situation, you have several alternatives:

  • Check if the modules providing the filters have a Drupal 8+ version and install them
  • Edit and save the affected input formats. This will remove the reference to format_null, and the contents will start showing. Note that since the original filter doesn't exist, contents are not being filtered and unreplaced tokens may be shown, or even the site can be exposed to any security issue
  • Edit the contents and change to another input format. This suffers the same problems as the previous point

Duplicate field _config_instances

The problem

Drupal 7 allows duplicate field_name_bundle entries in their "field_config_instance" database. The "field_name_bundle" is a Drupal 8+ index key which consists of "field_name", "entity_type" and "bundle". This index key is unfortunately NOT unique and therefore allows multiple duplicate entries. 
This leads to migrations, which depend on "upgrade_d7_field_instance" to throw the following error while migrating, even if "upgrade_d7_field_instance" successfully migrated before

[error] Migration upgrade_d7_field_instance_widget_settings did not meet the requirements. Missing migrations upgrade_d7_field_instance. requirements: upgrade_d7_field_instance.

The solution

Look for duplicate "field_name", "entity_type", "bundle" combinated entries inside the "field_config_instance" d7 source database and delete them.

For more information, see #3307506: "Missing migrations upgrade_d7_field_instance" because of duplicate field_name_bundle entries in D7 field_config_instance.

Files

File entity

If your source Drupal 7 site is using File Entity then the filename in the database may be the title not the filename on disk. After the migration this may result in errors when editing migration content type that use a file field. To prevent this a custom migration is needed. An example is in #3022910: Prevent migrated files from having an incorrect value at file_managed.filename.

Migrating Files fails

If your source Drupal 7 site is using a non-standard path for the public file system i.e anything other than sites/default/files, you may experience issues when attempting to migrate physical files:

Migrating Files and assets
[notice] Processed 7065 items (0 created, 0 updated, 7065 failed, 0 ignored) - done with 'upgrade_d7_file'
[error] upgrade_d7_file Migration - 7065 failed.

This means Drupal 8+ can read that there are 7065 file entities in the Drupal 7 database, but it can't reach the physical files themselves. This error will also lead to the Media entity migration failing, as the files are not present for the entity to link.

This may be because regardless of the file location you specify in your file migration (migrate_plus.migration.upgrade_d7_file.yml), and any override for the system file path defined in settings.php, the Migrate module will query the Drupal 7 database directly to get the file path and ignores all other settings.

The file path the Migrate modules use will be stored in the variable file_public_path.

To check what your Drupal 7 system file path is, in your D7 site run $ drush vget file_public_path, and $ drush vget file_temporary_path for temp files.

Note: However, that the vget result can be misleading. If you have specified a different file path in your settings.php or settings.local.php, the drush command will return that value instead, NOT the value stored in the database! To ensure you get the value Migrate will use, ensure you haven't overridden the file path in D7's settings.php or settings.local.php:

$conf['file_public_path'] = '/my/great/file/path';
$conf['file_temporary_path'] = '/some/temp/path';

Remove any overrides, then check the variable value. If you want to change it, run: $ drush vset file_public_path = /place/my/files/live (normally sites/default/files).

Plain Text Fields

Conflicting text processing settings in Drupal 7

In Drupal 7, the text processing settings are defined on Field instance settings. In other words, the same field can be used on two (or more) content types and the text processing settings can be Plain text on one content type and Filtered text on another.

Drupal 8+ has separate field storage types Text (plain) and Text (formatted). There's also Text (plain, long) and Text (formatted, long). The important part here is that this selection is done on the field storage level. In other words, the plain/formatted selection can't be changed per content type.

The migration system makes no assumptions. If the migration system detects conflicting text processing settings, these fields are skipped with a log message. The site builder has two options:

1. The text processing settings can be altered on a Drupal 7 site so that all content types that use the text field have the same text processing setting.

  • Pay attention when selecting which way to harmonize the processing settings to avoid possible cross-site scripting (XSS) security issues.
  • If your field was set to Plain text in Drupal 7 and untrusted users were able to post content to this field, it is possible that the fields contain malicious input. This was not leading to an XSS on your Drupal 7 site because the field was set to Plain text and thus the malicious input was not executed. If you now change the field now to Filtered text, make sure that the Text format is not Full HTML or similar which would allow the malicious input.

2. If you need to have two different formatting settings in the destination site, you need to develop a custom migration that splits the Drupal 7 fields into two separate fields. Find more information on customizing the migrations read Customize migrations.

Text with summary + plain text formatting setting in Drupal 7

Drupal 7 has a field type with Long text and summary. The corresponding field type in Drupal 8+ is Text (formatted, long, with summary). In Drupal 7 it is possible to configure on field instance settings that the text processing is Plain text. The Text (formatted, long, with summary) fields are always formatted text in Drupal 8+.

The migration system makes no assumptions. If the migration system detects a Long text and summary field with Plain text formatting settings, the field is skipped with a log message. The site builder has the same two options as above:

1. Change the field formatting setting from Plain text to Filtered text in Drupal 7.

  • The same remark described above about cross-site scripting applies here.

2. Create a custom migration path and build your own logic on how you want to migrate the fields to the destination site. Find more information on customizing the migrations read Customize migrations.

Text with summary: Individual value, summary and format migration through one process plugin

Sometimes it is needed to migrate the value, summary and format of a textarea field for a certain content bundle individually, because you are using different filter formats on your d9 site, compared to your d7 site. So instead of using the generated "get" process plugin, example:

process:
  body:
    -
      plugin: get
      source: body

We can use the "sub_process" plugin instead, to individually process "value", "summary" and "format" like this:

process:
  body:
    plugin: sub_process
    source: body
    process:
      value: value
      summary: summary
      format:
        plugin: static_map
        source: format
        map:
          full_html: full_html
          filtered_html: basic_html
          pure_html: full_html
          plain_text: plain_text
          php_code: full_html

This way, it is possible to use different plugins for each textarea attribute, like "static_map" in the example above, or just plainly map the data (e.g. value: value). If you do not want to override every single generated Migration YAML, you can also perform the override using "hook_migrations_plugins_alter()".

Rules

Help improve this page

Page status: No known problems

You can: