When a migration defines an entity reference and therefor depends upon another 2nd migration which gets run at a later time (thus not enforced via "migration_dependencies: required: ...") the migration will fail if the 2nd migration has Substr as one of the used plugins.

When the migration runs the entity references are created as stubs. The stubs are created creating a Row with only the target_id filled out, the rest of the values are empty. This stub row is then processed by the 2nd migration. When the 2nd migration defines Substr as the plugin for one of the values the Substr plugin will have to process a NULL value and throw MigrateException('The input value must be a string.');

This background-run of the 2nd migration on a stub row to create the entity-reference in the 1st migration effectively fails the whole migration.

The fix is to check for null on $value. If it is NULL then just return $value (NULL) because there won't be anything for Substr to do on NULL.

Members fund testing for the Drupal project. Drupal Association Learn more

Comments

Jeroen created an issue. See original summary.

Jeroen’s picture

Jeroen’s picture

Jeroen’s picture

Jeroen’s picture

I've added a test too.

benjy’s picture

This stub row is then processed by the 2nd migration. When the 2nd migration defines Substr as the plugin for one of the values the Substr plugin will have to process a NULL value and throw MigrateException('The input value must be a string.');

Is this because the values are null in the source data? I'm not opposed to adding your check to the substr plugin but I think it could also be solved with:

myfield:
  -
    plugin: skip_on_empty
    method: process
    source: mysource_field
  -
    plugin: substr
mikeryan’s picture

Status: Needs review » Postponed (maintainer needs more info)

Sorry Jeroen, now that I look closely at other string-manipulating process plugins such as explode and machine_name, I'm not sure the special NULL handling is appropriate here. The throwing of MigrateException is our established pattern in the !is_string() case - I agree it's harsh to hard-code throwing out the whole row for a missing value in one field (I think it would be better to return NULL and anyone who wanted to throw it out could chain to skip_on_empty with method: row), but at this point changing that behavior would be a backwards-compatibility break. And even if we thought it was worth a BC break, it's something that should be applied to all the process plugins, not just singling out this one. As benjy points out, you do have the option to skip_on_empty upstream.

Your stub problem is more general than substr - basically, in any scenario where stubbing may occur, the migration creating the stub must be prepared for empty values in all fields. I could have sworn we had at some point discussed adding a mechanism for providing default source values for stubs via the migration process plugin, but can't find such an issue for it at the moment. Unless/until we did something like that, I think about all we can do is document that you need to bullet-proof any migrations which are used for stubbing.

mikeryan’s picture

Title: Migrate's Substr plugin makes a stub-migration fail. » Document that migrations used for stubbing need to deal with empty source values
Assigned: Jeroen » Unassigned
Category: Bug report » Task
Status: Postponed (maintainer needs more info) » Active
Issue tags: +documentation

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

agileadam’s picture

I just ran into this issue related to substr. Unfortunately it cannot be solved by simply adding a skip_if_empty plugin before substr in the chain. If you use skip_if_empty and you are re-running a migration (--update and/or track_changes: true) and a field that previous had values now no longer has values, the field will be ignored during the migration process and the old field data will be kept in the entity. I can confirm that adding the if null check solves this issue.

It happens with the StaticMap process plugin as well. I'm about to go see if an issues exists for that one.

agileadam’s picture

Here's a patch (against 8.3.7) that adds NULL handling and associated tests to Concat, Substr, and StaticMap. I've tested on about 30 migrations (100k records) without issues (FWIW). I will create a patch against 8.4.x-dev if/when time allows.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.