InvalidArgumentException: Routing requirement for "_bundle" must be a string is being thrown when I run a custom migration using migrate_plus. As a result drush cr all, drush mi, drush ms are all throwing the same exception. So a work around is drush mrs then disable jsonapi

Comments

mwebaze created an issue. See original summary.

wim leers’s picture

Status: Active » Closed (cannot reproduce)
Issue tags: -Routing exception +Needs steps to reproduce

I can't reproduce this.

This exception must've been thrown by \Symfony\Component\Routing\Route::sanitizeRequirement(). That could only have been triggered by \Drupal\jsonapi\Routing\Routes::routes() in JSON API, where it does ->setRequirement('_bundle', $resource_type->getBundle()). But the ResourceType value objects are generated by \Drupal\jsonapi\ResourceType\ResourceTypeRepository::all(), which calls core APIs directly. I should be able to reproduce this bug, but I can't.

I suspect something changed in Migrate and/or JSON API that fixed this.

Feel free to reopen this, but if you do, please provide steps to reproduce.

wim leers’s picture

idebr’s picture

Status: Closed (cannot reproduce) » Active
Issue tags: -Needs steps to reproduce
StatusFileSize
new72.41 KB

This can be reproduced following these steps:

  1. Create a webform with a numeric title, for example "25012018"
  2. Rebuild router, for example by rebuilding cache

The $resource_type is then defined as:

gabesullice’s picture

Status: Active » Closed (works as designed)

I think Drupal core expects the bundle type to be a string, see:

https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Entity%21...

So, I think this issue should be moved to migrate module. I think all they'll have to do is cast the bundle name to a string somewhere... return (string) $bundle_id;.

idebr’s picture

Status: Closed (works as designed) » Needs review
StatusFileSize
new1.37 KB

@gabesullice Thank you for taking a look at this issue.

I think Drupal core expects the bundle type to be a string, see:

https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Entity%21...

So, I think this issue should be moved to migrate module. I think all they'll have to do is cast the bundle name to a string somewhere... return (string) $bundle_id;.

For example in the node module, the bundle is saved as an entity reference. Even when a bundle is saved as a string containing only integers, the bundle id is returned as an integer rather than a string. Attached patch expands the ResourceTypeRepositoryTest to show this is the current behavior in Drupal core.

I am not suggesting this is the expected (or even correct) behavior, but it is currently the JSON API module that is asserting every bundle is returned as a string. Can I ask you to reconsider this assertion given this current behavior in Drupal core?

Status: Needs review » Needs work
gabesullice’s picture

Version: 8.x-1.0 » 8.x-1.x-dev
Status: Needs work » Needs review
StatusFileSize
new1.17 KB
new4.37 KB

@idebr, thanks for sticking to your guns and also thanks for the patch. I stand corrected. I tried to follow my own advice and patch this in core only to realize that it can't be fixed (in core). This is because the entity type bundle info service uses the bundle ids as keys to an array. Even if you cast the numbers to strings, PHP will just cast them back to integers:

Strings containing valid decimal integers, unless the number is preceded by a + sign, will be cast to the integer type. E.g. the key "8" will actually be stored under 8. On the other hand "08" will not be cast, as it isn't a valid decimal integer.

Given the interface for setRequirement is Route::setRequirement(string $key, string $regex), I do now believe it's on us to fix.

@idebr, thanks again for sticking with it.

Note: No interdiff because I wrote a different set of tests to show the reported exception in the IS

The last submitted patch, 8: 2900459-8.tests_only.patch, failed testing. View results

idebr’s picture

Status: Needs review » Reviewed & tested by the community

@gabesullice Cheers! Your patch solves the problem at hand elegantly and the added test coverage should prevent this problem in the future. Many thanks!

wim leers’s picture

Status: Reviewed & tested by the community » Fixed

Great find! Thanks everyone :)

Also: TIL bundles can be integers! I had no idea that was even possible, or I'd have mentioned it in #2.

Finally: special thanks to @idebr, for finding a pre-existing issue that was closed with inaccurate reasoning (by me), then reopening it with actual steps to reproduce.

gabesullice’s picture

Also: TIL bundles can be integers! I had no idea that was even possible

Technically, bundle IDs can't be integers. It's just that PHP might cast them to integers *if you get them from the bundle info service*. Every Drupal interface I could find indicated that they must to be strings, the most important being EntityTypeInterface::id() which indicates the ID must be a string.

wim leers’s picture

I think you meant \Drupal\Core\Entity\EntityTypeInterface::BUNDLE_MAX_LENGTH?

Status: Fixed » Closed (fixed)

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