If the process pipeline fails due to array/scalar values, the exception message is:

> Pipeline failed for destination %s: %s got instead of an array

This tells you which field mapping failed, but if that mapping has a several process plugins, then you're still not sure where exactly the problem lies.

Including the plugin ID would help with this (though it's true that the same plugin could feasibly be used more than once...)

Comments

joachim created an issue. See original summary.

joachim’s picture

Status: Active » Needs review
StatusFileSize
new875 bytes

The plugins array is not keyed numerically, so getting the order of the failing plugin would require a bit more work. I reckon giving the plugin ID should be enough.

mikeryan’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests
+++ b/core/modules/migrate/src/MigrateExecutable.php
@@ -358,7 +358,7 @@ public function processRow(Row $row, array $process = NULL, $value = NULL) {
+            throw new MigrateException(sprintf('Pipeline failed at %s plugin for destination %s: %s got instead of an array,', $plugin->getPluginId(), $destination, $value));

While we're at it, "got" isn't very elegant English here... Maybe we can change it to "received"?

That's a nit - needs work because needs tests. Given that the tests passed, that suggests this exception is not currently tested, good opportunity to add one...

Thanks!

jofitz’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
StatusFileSize
new2.8 KB
new1.9 KB
new2.76 KB

Added test.

The last submitted patch, 4: 2846002-4-test_only.patch, failed testing.

phenaproxima’s picture

Priority: Minor » Normal

This would be a big usability win for Migrate. Kicking it up a notch.

phenaproxima’s picture

Assigned: Unassigned » phenaproxima

Self-assigning for review.

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

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now 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.

phenaproxima’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/migrate/tests/src/Unit/MigrateExecutableTest.php
    @@ -420,6 +420,40 @@ public function testProcessRowEmptyPipeline() {
    +      $plugins['destination_id'][$key] = $this->getMock('Drupal\migrate\Plugin\MigrateProcessInterface');
    +      $plugins['destination_id'][$key]->expects($this->once())
    +        ->method('getPluginDefinition')
    +        ->will($this->returnValue(['handle_multiples' => FALSE]));
    +      $plugins['destination_id'][$key]->expects($this->atMost(1))
    +        ->method('transform')
    +        ->will($this->returnValue('transform_return_string'));
    +      $plugins['destination_id'][$key]->expects($this->atMost(1))
    +        ->method('multiple')
    +        ->will($this->returnValue(TRUE));
    +      $plugins['destination_id'][$key]->expects($this->atMost(1))
    +        ->method('getPluginId')
    +        ->will($this->returnValue('plugin_id'));
    

    Can this be changed to use Prophecy? It's a lot more readable. If we don't want to switch to Prophecy, we should have comments to improve grokkability.

  2. +++ b/core/modules/migrate/tests/src/Unit/MigrateExecutableTest.php
    @@ -420,6 +420,40 @@ public function testProcessRowEmptyPipeline() {
    +    try {
    +      $this->executable->processRow($row);
    +      $this->fail('Pipeline exception should throw.');
    +    }
    +    catch (MigrateException $e) {
    +      $this->assertEquals('Pipeline failed at plugin_id plugin for destination destination_id: transform_return_string received instead of an array,', $e->getMessage());
    +    }
    

    Rather than try/catch, let's take advantage of PHPUnit's @expectedException and @expectedExceptionMessage annotations.

jofitz’s picture

Status: Needs work » Needs review
StatusFileSize
new2.75 KB
new2.65 KB
  • Changed from using getMock() to prophesize() for improved readability.
  • Used @expectedException and @expectedExceptionMessage - what an awesome, elegant code structure. Love it! @phenaproxima++
phenaproxima’s picture

+++ b/core/modules/migrate/tests/src/Unit/MigrateExecutableTest.php
@@ -420,6 +421,31 @@ public function testProcessRowEmptyPipeline() {
+    $this->migration->expects($this->once())
+      ->method('getProcessPlugins')
+      ->with(NULL)
+      ->will($this->returnValue($plugins));

One tiny thing, for brevity's sake. This can be rewritten:

$this->migration->method('getProcessPlugin')->willReturn($plugins);

Let us change it to that, and then this is good to go! Excellent work, @Jo Fitzgerald. Thank you!

jofitz’s picture

StatusFileSize
new790 bytes
new2.58 KB

Done - much nicer!

Status: Needs review » Needs work

The last submitted patch, 12: 2846002-12.patch, failed testing.

jofitz’s picture

Status: Needs work » Needs review
StatusFileSize
new715 bytes
new2.58 KB

Typo!

phenaproxima’s picture

Status: Needs review » Reviewed & tested by the community

Glorious.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 14: 2846002-14.patch, failed testing.

jofitz’s picture

Status: Needs work » Reviewed & tested by the community

Seems to have been a testbot glitch, back to RTBC.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 14: 2846002-14.patch, failed testing.

tameeshb’s picture

Status: Needs work » Reviewed & tested by the community
t3rabyt3@imt3rabyt3-LY710 /v/w/h/drupal84> git apply --check 2846002-14.patch 
t3rabyt3@imt3rabyt3-LY710 /v/w/h/drupal84> 

Patch applies cleanly, not sure why the testbot says "PHP 5.6 & MySQL 5.5 Patch Failed to Apply"

jofitz’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new2.58 KB

Patch did not apply for me so re-rolled.

jofitz’s picture

Status: Needs review » Reviewed & tested by the community

Resetting to RTBC in expectation.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/modules/migrate/tests/src/Unit/MigrateExecutableTest.php
@@ -420,6 +421,28 @@ public function testProcessRowEmptyPipeline() {
+   * @expectedException \Drupal\migrate\MigrateException
+   *
+   * @expectedExceptionMessage Pipeline failed at plugin_id plugin for destination destination_id: transform_return_string received instead of an array,

We don't use annotations for this anymore. See #2822837: Replace @expectedException @expectedExceptionMessage with $this->setExpectedException.

jofitz’s picture

Assigned: phenaproxima » Unassigned
Status: Needs work » Needs review
StatusFileSize
new1.15 KB
new2.54 KB

Replaced @expectedException, @expectedExceptionMessage with $this->setExpectedException.

phenaproxima-- for misleading me :p

phenaproxima’s picture

Status: Needs review » Reviewed & tested by the community

Hey now, this is news to me as well! :) Having just now glanced at the issue linked by @alexpott, the rationale for using setExpectedException() makes sense to me. I don't agree that it should always be used -- like if unit testing a single method that will throw an exception on failure -- but the decision has been made and I will abide by it.

Preemptively back to RTBC assuming the tests pass.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed and pushed 2421ca2 to 8.4.x and 0fdb7f3 to 8.3.x. Thanks!

Backported to 8.3.x as migrate is experimental and this is helpful.

  • alexpott committed 2421ca2 on 8.4.x
    Issue #2846002 by Jo Fitzgerald, joachim: Pipeline failure exceptions...

  • alexpott committed 0fdb7f3 on 8.3.x
    Issue #2846002 by Jo Fitzgerald, joachim: Pipeline failure exceptions...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.