When a migration (Foo) declares a dependency to another migration (Bar) and (Bar) has skipped some rows (return FALSE in prepareRow) then (Foo) will fail with an error even when (Bar) has been imported:

[error]  Migration Foo did not meet the requirements. Missing migrations Bar. requirements: Bar.
drush migrate:status Bar
 ----------- -------------- -------- ------- ---------- ------------- --------------- 
  Group       Migration ID   Status   Total   Imported   Unprocessed   Last Imported  
 ----------- -------------- -------- ------- ---------- ------------- --------------- 
  Foobar      Bar            Idle     254     253        1             2019-04-16     
 ----------- -------------- -------- ------- ---------- ------------- --------------- 

Comments

mpp created an issue. See original summary.

mpp’s picture

Issue summary: View changes
joachim’s picture

There is an inconsistency in how row skipping is handled:

- If one of the hooks invoked in SourcePluginBase::prepareRow() throws a MigrateSkipRowException, then the row is saved to the map.
- If one of the process plugins throws a MigrateSkipRowException, then the row is saved to the map
- If SourcePluginBase::prepareRow() returns FALSE to skip a row, then the row is NOT saved to the map, and we get this bug.

joachim’s picture

As a workaround, you can do the logic for skipping the row in SourcePluginBase::prepareRow(), then set a boolean for whether to skip the row to an arbitrary field name:

      $row->setSourceProperty('skip', $whether_to_skip);

and then use the skip_on_empty process plugin with an empty destination in the migration's config:

  null:
    plugin: skip_on_empty
    method: row
    source: skip
    message: 'Skipping!'

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

yonailo’s picture

I think there is another case to take into account. If the destination key is already used. For exemple I have a migration which import files. The destination key is the "src" XML tag. If there are duplicate "src" elements, those duplicates will be counted as "unprocessed". In this particular case there are no exceptions thrown and prepareRow() does not return FALSE.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

joachim’s picture

Priority: Normal » Major

I'm going to up this to a major: a migration which uses prepareRow() as documented to skip a row then can't have another migration depend on it.

The crux of the problem is that things that want to check if a migration is complete just call the query, which returns a count. They don't do processRow() on each row. Meanwhile, actually running a migration lets you skip a single row and then considers that row as not existing in the source.

There are *two* different ways to count a migration's source rows and they *do not necessarily agree*!!

For example:

My migration source runs correctly:

> [notice] Processed 1980 items (1980 created, 0 updated, 0 failed, 0 ignored) - done with 'ex_group_membership_media'

But the status report says otherwise:

> Default (default) ex_group_membership_media Idle 1994 1980 14 2021-02-03 14:30:33

That's because in 14 rows, prepareRow() in my source plugin returned FALSE to skip a row.

The fix here is that prepareRow() should behave the same way as the catching of exceptions from processRow(): mark the row in the map as ignored.

quietone’s picture

@mpp, thanks for the report.
@joachim, nice analysis.

The 'wrokaround' suggested in #4 is not merely a workaround, it is, in my opinion, the correct way to skip rows.

This is a duplicate of #2797505: Migrations fail due to missing dependency when dependency has skipped rows by the source plugin. Closing this and moving credit there