Problem/Motivation
Under certain circumstances, denormalizing HAL data that include the metatag pseudo-field can trigger the following error:
ResponseText: InvalidArgumentException: Field metatag is unknown. in Drupal\Core\Entity\ContentEntityBase->getTranslatedField()
This can occur for file entity data when Metatag is used in combination with Default Content and Better Normalizers, which provides a file entity normalizer. Steps to reproduce:
- Install Metatag, Default Content, and Better Normalizers.
- Use the Default Drush command to export HAL json for a file entity to a custom module.
- On a fresh site, install Metatag, Default Content, and Better Normalizers and then install the custom module.
The error results. Here is the error with a partial backtrace:
InvalidArgumentException: Field metatag is unknown. in Drupal\Core\Entity\ContentEntityBase->getTranslatedField() (line 509 of core/lib/Drupal/Core/Entity/ContentEntityBase.php).
Drupal\Core\Entity\ContentEntityBase->get('metatag') (Line: 123)
Drupal\hal\Normalizer\ContentEntityNormalizer->denormalizeFieldData(Array, Object, 'hal_json', Array) (Line: 172)
Drupal\hal\Normalizer\ContentEntityNormalizer->denormalize(Array, 'Drupal\file\Entity\File', 'hal_json', Array) (Line: 42)
Drupal\better_normalizers\Normalizer\FileEntityNormalizer->denormalize(Array, 'Drupal\file\Entity\File', 'hal_json', Array) (Line: 250)
Symfony\Component\Serializer\Serializer->denormalizeObject(Array, 'Drupal\file\Entity\File', 'hal_json', Array) (Line: 160)
Symfony\Component\Serializer\Serializer->denormalize(Array, 'Drupal\file\Entity\File', 'hal_json', Array) (Line: 118)
Symfony\Component\Serializer\Serializer->deserialize(Array, 'Drupal\file\Entity\File', 'hal_json', Array) (Line: 183)
Drupal\default_content\Importer->importContent('my_custom_module') (Line: 15)
default_content_modules_installed(Array)
The issue appears to involve the interaction of the MetatagHalNormalizer
in metatag
and FileEntityNormalizer
in better_normalizers
. The services for these normalizers both have priority of 30.
The MetatagHalNormalizer
adds a metatag
pseudo-field and the better_normalizers
FileEntityNormalizer
normalizer one adds a data
pseudo-field. While MetatagHalNormalizer
does not support denormalization, FileEntityNormalizer
does. In its ::denormalize()
call, it removes its own pseudo-field and then calls the parent ::denormalize()
method. The metatag
pseudo-field has not been removed, and core raises an exception.
The lines where the exception is raised are:
$definition = $this->getFieldDefinition($name);
if (!$definition) {
throw new \InvalidArgumentException("Field {<span class="php-variable">$name</span>} is unknown.");
}
Metatag is setting a metatag
base field in metatag_entity_base_field_info()
, which should prevent this error. The following code confirms that the metatag field is among those returned by EntityFieldManager::getFieldDefinitions()
:
$entity_type_id = 'node';
$bundle = 'article';
$definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions($entity_type_id, $bundle);
dsm(array_keys($definitions));
Comments
Comment #2
nedjoThe lines where the exception is raised are:
Metatag is setting a
metatag
base field inmetatag_entity_base_field_info()
, which should prevent this error. The following code confirms that the metatag field is among those returned byEntityFieldManager::getFieldDefinitions()
:I'm hitting this error at site install time. Possibly a caching issue prevents the metatag base field definition from being returned.
Comment #3
AndyF CreditAttribution: AndyF at TES Global commentedI think I just ran into the same thing. I'm also using default_content and better_normalizers, though I'm not sure if the latter is related.
In my case it seems to be caused by paragraph entities. After #2899752: Attempt to create a base field bundle override of field Metatags without an entity_type in Drupal\Core\Field\Entity\BaseFieldOverride landed, the base field addition was made conditional. So IIUC, if you have any entities that are now excluded from the metatag base field, exported with the old version of metatag, you'll get this error. I don't have much paragraph content so I just manually removed the metatag field; presumably you could also run a content export after a module update to avoid the problem.
Comment #4
seanBJust ran into this as well. When looking at
\Drupal\hal\Normalizer\FieldItemNormalizer::normalize()
we see the following code:Currently, the metatag normalizer
Drupal\metatag\Normalizer\FieldItemNormalizer
is not wrapping the values which causes an exception. I guess we need a separate normalizer to support hal_json.*EDIT: There is a separate normalizer for hal_json:
Drupal\metatag\Normalizer\MetatagHalNormalizer
. Not sure why it is not being used yet.*EDIT2: The
Drupal\metatag\Normalizer\MetatagHalNormalizer
supportsDrupal\metatag\Plugin\Field\MetatagEntityFieldItemList
whileDrupal\metatag\Normalizer\FieldItemNormalizer
supportsDrupal\metatag\Plugin\Field\FieldType\MetatagFieldItem
. When using a manually created metatag field (through the interface) with the hal_json format, it uses theFieldItemNormalizer
which doesn't support hal_json. We still need a hal json formatter for that one. Since that is not about the pseudo field it is probably a separate issue.Comment #5
idebr CreditAttribution: idebr at iO commentedThis will probably be fixed with #2945817: Support JSON API, REST, GraphQL and custom normalizations via new computed field
Comment #6
DamienMcKennaPlease test out the new Metatag 2.0.0 release that includes plugin which provides normalized output (from #2945817).