For some reason after enabling the module on my site and trying a GET request like:
/jsonapi/node/article?_format=api_json
I receive the error:
The website encountered an unexpected error. Please try again later.
Error: Call to a member function setPropertyType() on array in Drupal\jsonapi\Normalizer\EntityNormalizer->serializeField() (line 223 of modules/contrib/jsonapi/src/Normalizer/EntityNormalizer.php).
This happens with all content types.
I've tried it on a vanilla site and this type of request works fine so it must be something about this site but I'm not sure what might cause it. Does anyone have suggestions of things I might look at? Thanks!
Comments
Comment #2
acbramley commentedI've just seen this happen on my site as well, but on taxonomy entities.
Debugging into it it looks like it's the Metatags field added by the metatag module.
$field was an instance of MetatagEntityFieldItemList, when that gets normalized it runs through MetatagNormalizer which simply returns an array rather than a FieldNormalizerValueInterface object that's expected.
This could happen with other contrib modules that add their own fields and normalizers too.
I'm not sure if @attheshow's issue is also caused by the metatag module.
Comment #3
e0ipsoThis may be an issue in metatags. See: #2903457: Normalizer problem when Metatag is enabled.
Comment #4
e0ipsoComment #5
acbramley commentedThat issue doesn't seem related at all?
I think at the very least, jsonapi should be a bit defensive in order to avoid other contrib modules breaking its functionality. Adding a check of the instance of the $output variable would stop this kind of thing breaking jsonapi entirely.
Comment #6
attheshow commentedThanks so much for helping me figure this one out. Confirmed. As soon as I uninstalled Metatag the issue disappeared. After re-installing Metatag the problem reappeared.
Comment #7
e0ipsoNot sure what are you basing that on. It is a known issue that Metatags normalizer is too greedy and tries to do its thing when it should not.
That's a good approach. I like it! Would you care providing a patch for review?
Thanks!
Comment #8
acbramley commentedThis fixes the issue for me, I have looked into the tests and not too sure where this sort of thing would fit in. Happy to give the tests a go if you can point me at the right place :)
Comment #9
wim leersSounds like this is another problem caused by #2852860: REST: top priorities for Drupal 8.4.x.
Comment #10
wim leersThat was supposed to be #2860350: Document why JSON API only supports @DataType-level normalizers.
Comment #11
wim leers#3 linked to an issue without adding it as a related issue. Fixing.
Comment #13
e0ipsoThanks @acbramley. I committed the improvement!
Comment #14
wim leersThis still needs test coverage?
Comment #15
acbramley commented@Wim Leers yeah it does, afaict we'd need to implement a test module that implemented a field normalizer similar to what metatag does?
Comment #16
spoorthy01 commented@acbramley, I had same error in EntityNormalizer.php. I applied your patch to Drupal Thunder distribution. Now I get different error - Call to undefined method Drupal\Core\StringTranslation\TranslatableMarkup::getInclude() in C:\DrupalThunder\modules\jsonapi\src\Normalizer\Value\FieldNormalizerValue.php on line 53
Comment #17
acbramley commented@spoorthy01 which EntityNormalizer is that happening on? It looks like jsonapi needs to be defensive there as well since it is expecting the array $values to be an array of FieldItemNormalizerValue objects.
Comment #18
spoorthy01 commented@acbramley Initially the error was in modules\jsonapi\src\Normalizer\EntityNormalizer.php. The error was "Call to a member function setPropertyType() on a non-object". After updating JSON API module to 8.x-1.2, a new error in modules\jsonapi\src\Normalizer\Value\FieldNormalizerValue.php on line 53 has occured. The error says "Call to undefined method Drupal\Core\StringTranslation\TranslatableMarkup::getInclude()".
Comment #19
kybermanHi, I have the same error as @spoorthy01. with the same scenario:
- version 1.1 -> "setPropertyType() on array" error
- version 1.2 -> "undefined method TranslatableMarkup::getInclude()" error
Comment #20
kyberman@spoorthy01 @acbramley I found that this problem was when using together with Metatag module and this patch helped me as temporary fix - https://www.drupal.org/node/2636852#comment-12247973. I'm using jsonapi 1.3 and current metatag dev.
Comment #21
ebeyrent commentedI'm running into the same issue after adding a Normalizer to the contrib Serial module. I get:
Error: Call to a member function getInclude() on array in Drupal\jsonapi\Normalizer\Value\FieldNormalizerValue->Drupal\jsonapi\Normalizer\Value\{closure}() (line 53 of /web/modules/drupal/jsonapi/src/Normalizer/Value/FieldNormalizerValue.php) #0Comment #22
ebeyrent commentedThis patch appears to resolve the issue I documented in #21.
Comment #24
e0ipsoI made some minor modifications on commit.
Comment #25
wim leersAre we okay with this going in without test coverage?
Comment #26
e0ipsoI'm leaning towards, yes. Even though it's obviously preferable to have test coverage there are several abandoned patches waiting for test coverage. I don't want the patches that are simpler to follow that fate.
I'm OK leaving this as needs work to add more tests, but I'd rather not halt all patches on this premise (some time that is ok though).
Comment #27
wim leers#26: I understand that, and it's fine for a contrib module. But unfortunately, this does mean it continues to get harder and harder to get this module into core. Comments like #26 make core committers very reluctant to add this to core…
Comment #28
e0ipso@Wim Leers agreed. Whenever we pull this into core, we'll need to harden test coverage. I was trying to say that I'm OK having some issues merged with a test follow-up. In my experience, asking for tests tends to halt progress on the issue making it stale (although not always).
So, I think we are on the same page?
Comment #29
wim leersThat's works in an ideal world.
That's true.
There are consequences to this pragmatism: the necessary regression tests are never written, allowing the same regressions (or related ones) to be introduced later.
We're kind of on the same page, but not quite:
Comment #30
e0ipsoWon't this be covered by the comprehensive test coverage epic?
Leaving it broken/uncommitted because there are no tests is not ideal. Having no tests to prevent regressions is not ideal. What can be a good balance here?
Comment #31
wim leers#2930028: Comprehensive JSON API integration test coverage phase 1: for every entity type, individual resources only will add integration tests for every entity type, to verify you can do CRUD on all entity types, and will help ensure no BC breaks in the normalization. But it's not going to test every minute detail. Maybe it'll catch this, maybe it won't. I think it's unlikely.
Indeed! It's a hard line to walk.
I think that a simple way to deal with this can be:
Comment #32
ebeyrent commented@e0ipso I finally got to test this, and it looks like you made a change to my patch which breaks my patch. Instead of returning the value, it's returning NULL. When I reinstate my change, I start seeing the value again.
@Wim Leers I'm happy to provide test coverage for this, but I could use some guidance as to how to provide a situation where there's a new field type with a custom normalizer. Any suggestions?
Comment #33
ebeyrent commentedComment #34
e0ipsoKicking off tests.
Comment #36
e0ipso@ebeyrent it seems that the patch you provided cannot be applied anymore. Can you do a re-roll?
Comment #37
wim leersWriting tests for this is pretty much impossible at this point, because several issues have been committed that fix bugs in this area. For example #2939800: FieldNormalizerValue::rasterizeValue() respects cardinality === 1, but doesn't verify that this is true and #2940342: Cacheability metadata on an entity fields' properties is lost.
Plus, we have the #2930028: Comprehensive JSON API integration test coverage phase 1: for every entity type, individual resources only integration test coverage plus follow-ups.
Closing as a duplicate.
Comment #38
Houmanvg commentedThis issue is still not fixed.
I tested the patch, and it indeed does not fix the issue for JSONAPI.
The issue occurs when;
- fetching a node (the serial filed value fetched is showed as an empty array, and when;
- Creating a node (the serial field value is not inserted)
Comment #39
wim leers@Houmanvg: please create a new issue with clear steps to reproduce. Thank you 🙏
Comment #40
ebeyrent commentedSee https://www.drupal.org/project/serial/issues/2921349