LanguageTest::testCurrentPageLanguageTokenReplacement() not using correct dataProvider attribute
Make the image style tokens work with all compatible field types
I'm using Supported Image Field which extends core's Image field type and would love to use image style tokens with supported image fields. Currently that's not possible because Token module defines those tokens only for core's Image field type.
Note that I did verify that this check $field->getType() == 'image' is the only reason for image style tokens not to work with supported image fields. As a quick experiment, I updated the check to include supported_image field type and image tokens worked just fine.
Steps to reproduce- Install Supported Image Field module.
- Create and configure field of a type "Supported Image". E.g. field_supported_image.
- Define token that is using supported image field and image style. E.g. [node:field_supported_image:large] where "large" is the name of an image style.
- Confirm that the output of this token is empty.
In addition to checking if the field type is image, also check if the field has capability to support image style tokens. Below are some ideas how to do that.
/** * Implementation of hook_tokens() in Token module. */ // Current code: Check only for the field type. if ($field_item->getFieldDefinition()->getType() == 'image') {} // Option 1: Implicitly assume if the field extends ImageItem it must be // compatible. No need for other field types to declare anything. if (($field_item instanceof \Drupal\image\Plugin\Field\FieldType\ImageItem)) {} // Option 2: Define empty (marker) interface for this purpose and check if the // field type implements it. if ($field_item->getFieldDefinition()->getType() == 'image' || $field_item instanceof ImageFieldCompatible) {} // Option 3: Check for the boolean attribute defined on the field type. if ($field_item->getFieldDefinition()->getType() == 'image' || !empty($field_item->getPluginDefinition()['add_image_style_tokens'])) {}Note: Options 2 and 3 still contain the check for image field type in order to avoid having to modify core's image module.
I like the simplicity of Option 1 but I'm not sure if assumption its making is safe enough.
Making this change would enable any other compatible field type to take advantage of image style tokens. I didn't check if there are any other modules currently that could benefit from this change in addition to Supported Image Field.
Remaining tasksDecide which approach to take and implement the solution.
User interface changesNone.
API changesTBD
Data model changesNone.
Field value tokens chained through entity reference fields do not check access to the referenced entity
This issue has been tagged for public follow-up by the Drupal security team.
This module has an Information Disclosure vulnerability.
Token module extends Drupal's token system to allow for chained tokens through entity reference fields. When a token such as [node:field_profile:entity:field_first_name:value] is in use, the field value will be shown even if the entity referenced via field_profile is unpublished.
Steps to reproduce:
1. Install Token
2. Create a Profile content type, with a field_first_name plain text field
3. Add a Profile entity, fill in First Name field; save it unpublished
4. Create an Article content type, with a field_profile reference field
5. Add an Article entity, reference the Profile added in #3
6. Call `Drupal::token()->replace('[node:field_profile:entity:field_first_name:value]', ['node' => $node])` somewhere like a page controller or hook_preprocess_node() to print the output (or use Metatag module)
7. View Article page from #5 as an anonymous user
Expected outcome: the First Name value from the unpublished Profile node should not be displayed
Actual outcome: the First Name value is shown.
- Version: 8.x
- Original reporter: les lim
- Initially created: Tue, 2023-01-10 14:33
Discussion in the private issue was centered around whether and how token access checking should work. Key points raised:
- The token API was designed without access control by default, so tokens have historically been treated as safe only for admin-like users who can view all content.
- Metatag doesn't interact with token access and may not be able to.
- A proposal to add an optional check_access option to Token::replace() ran into the problem of when and as whom to check. Access may need checking at configuration time (where no concrete entity or user exists) as well as replacement time, and using the current/global user at runtime is problematic.
- Some entities (e.g. taxonomy terms used as keywords) might legitimately surface even when the viewing user lacks access to the entity's canonical page, especially where modules like RabbitHole only override the page controller without touching access control. This was partially accepted, with the caveat that genuine $entity->access() failures should still suppress output.
Add token for most recent entity revision
In a project I needed to display, using tokens, the most recent revision's data in a message. Since there is a moderation though, the data retrieved by the tokens were the latest active revision's and not the most recent's one.
Proposed resolutionProvide a new [node:latest-revision:*] token which will act (a) for all revisionable entity types and (b) like [node:*] but for the latest revision.
Existing issuesThere are already a few issues related but for earlier versions of this module: #252241: Add tokens for node revision timestamp, author, and log message and #992646: Add a 'node revision' token type.
Provide bundle-scoped tokens in addition to entity-type scoped tokens
When browsing tokens for a specific bundle (which is 98% of the time), it would be a big usability boost to only see fields that belong to that bundle.
And, a bit more of an edge case, there are uses where different entities may be the source of token replacements but you would only want [node:label] to do its thing and give you the title if the source entity were an article and not a page, so [nodebundle:article:label] or something like that, while [nodebundle:page:label] would only be filled when a node of type page is available. This is the case for FillPDF and its use of tokens: #3591673: Scope field token replacement to a bundle
Steps to reproduce Proposed resolutionBoth these use cases could be addressed by providing scoped tokens, either under node [node:article:label] or maybe directly as the bundle machine name [article:label] but that would presumably have risk of namespace collisions, or else (safest?) under a separate namespace, say [nodebundle:article:label]
Remaining tasksDecide if this would be accepted into token module, and then how the namespace should work.
User interface changesYet more tokens, but once you are in the tree for your bundle you only see the fields relevant to your bundle.
API changes Data model changesTokenModuleProvider writes stale in memory data back to cache.bootstrap after token_info tag invalidation
Hey!
Since token 1.17 introduced TokenModuleProvider (a
CacheCollector stored in cache.bootstrap), tokens
like [current-page:url] and [current-date:short]
can silently stop resolving after a token_info cache tag
invalidation, even though a full drush cr restores them.
Additionally, no hook_update_N was included in 1.17 to
invalidate the old token_info:{lang} cache key (renamed to
token_info_sorted:{lang}), so sites that did not run
drush cr on deploy hit this immediately.
- Upgrade to token 1.17 without running drush cr, OR
- On a site with token 1.17 installed: save a webform or trigger any
token_info tag invalidation. - Observe that [current-page:url] and
[current-date:short] render literally in webform emails
instead of being replaced. - Run drush cr — tokens work again.
- Trigger a token_info invalidation — tokens break
again.
Override Token::resetInfo() to also call
TokenModuleProvider::reset() before shutdown. This clears
$storage and $keysToPersist so
CacheCollector::destruct() has nothing stale to write back.
Also add token_update_8117() to invalidate
token_info on upgrade, so sites that did not run
drush cr after the 1.17 deploy are automatically
remediated.
None.
API changesToken::resetInfo() now also resets
TokenModuleProvider's in-memory state as a side effect. Any
caller that relied on TokenModuleProvider retaining its
storage after resetInfo() will rebuild from cache on next
access - which is the correct behaviour.
None.
Remove book tests and only define book tokens if there is no book_token_info()
#3562297: The token module does not currently support book 3.0.x or book 2.0.x added book tokens to book module, but token still defines it too.
Steps to reproduce Proposed resolutionAdd a check if the book token hook exists, then don't run ours, remove our tests.
Remaining tasks User interface changes API changes Data model changesAdd alt token image_with_image_style type
The module supports the tokens url, uri, width, height, filesize and mimetype for the image_with_image_style type, but no `alt` token for the alternative text of the image.
API changesImplement the alt token for image_with_image_style.
Drupal 12 compatibility, remove test dependency on contact module, remove migrataion tests
ServiceNotFoundException: TokenThemeHooks
After upgrading Drupal core to 10.6.7, the site threw a fatal error:
Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException:
You have requested a non-existent service "Drupal\token\Hook\TokenThemeHooks"
The site was completely unbootstrappable — drush could not run, cache clear was not possible.
Token version: 8.x-1.17
Drupal version: 10.6.7
PHP version: 8.3.29
SQL Server driver
Run a Drupal site with Token 8.x-1.17
Upgrade core to 10.6.7
Site becomes completely inaccessible
Downgrading Token to 1.16.0 resolved the issue.
Suspected cause:Token 8.x-1.17 registers TokenThemeHooks as an OOP hook service but something in the service registration is incompatible with Drupal 10.6.7's container.
[PHP 8.5] Warning with dynamic_entity_reference fields
This surfaced after migrating a project to PHP 8.5 on Dynamic Entity Reference fields . Suddenly I've noticed this error message:
Deprecated function: Using null as an array offset is deprecated, use an empty string instead in Drupal\token\TokenEntityMapper->getTokenTypeForEntityType() (line 72 of modules/contrib/token/src/TokenEntityMapper.php)
Tracking the error I see it happens in \Drupal\token\Hook\TokenTokenInfoHooks::fieldTokenInfoAlter(), lines ~693-694
$referenced_entity_type = $property_definition->getTargetDefinition()->getEntityTypeId(); $referenced_token_type = $this->tokenEntityMapper->getTokenTypeForEntityType($referenced_entity_type);The problem seems to be that $referenced_entity_type is computed to NULL. But the Dynamic Entity Reference field is a special kind of fish. Even it extends EntityReferenceItem the 'entity' field property doesn't set a target entity data definition because the target entity type is unknown and is assigned dynamically (see \Drupal\dynamic_entity_reference\Plugin\DataType\DynamicEntityReference).
Steps to reproduceClear the cache and visit Status report
Proposed resolutionOnly create the token if $referenced_entity_type is not NULL.
Remaining tasksNone.
User interface changesNone.
API changesNone.
Data model changesNone.
PHP8.5 Deprecation warning in TokenEntityMapper with
With PHP8.5 I get the following deprecation Warning on status page:
( ! ) Deprecated: Using null as an array offset is deprecated, use an empty string instead in /var/www/html/web/modules/contrib/token/src/TokenEntityMapper.php on line 72
It seems that $entity_type can be NULL in getTokenTypeForEntityType in some scenarios. I could track this down to https://www.drupal.org/project/dynamic_entity_reference module not providing an entity_type which makes sense. I am not sure if this is the right place to fix this though.
Steps to reproduce- Install dynamic_entity_reference and token
- Go to /admin/reports/status
- Add type check to dynamic_entity_reference
- Make sure tokens are only created if a reference entity type exists
Fix Object of class could not be converted to string in HtmlEscapedText error
Getting a Object of class ... could not be converted to string in Drupal\Component\Render\HtmlEscapedText->__construct().
Steps to reproduceThis is notoriously difficult to reproduce.
Proposed resolutionThis stems from a isset($field_item->$property_name) && ($field_item->$property_name instanceof FieldableEntityInterface conditional branch in Drupal\token\Hook\TokenTokensHooks::fieldTokens().
Token module is using isset($field_item->entity) as a gate to detect entity reference items before recursing for chained tokens (e.g. [user:field_ref:entity:url]). However, on EntityReferenceItem this is not reliable because FieldItemBase::__isset() delegates to Typed Data and returns FALSE when the underlying DataReference target is NULL, even if a valid target_id is present and __get('entity') would lazily resolve a real entity object. This leads to false negatives in the entity branch and causes the fallback to return an object (e.g. a Node, Meda, etc), ultimately triggering “Object of class … could not be converted to string” during rendering.
In other words, isset() here is checking typed data target state, not whether the property can resolve to a usable entity. The condition should instead rely on the dereferenced value (e.g. $value instanceof FieldableEntityInterface) or explicitly detect entity reference field types, rather than gating on isset().
I cannot currently reproduce this in a clean installation, but debugging the instance where I am seeing this confirms that isset($field_item->entity) returns FALSE while get_class($field_item->entity) returns a valid entity class in the same request, due to the Typed Data semantics described above.
Additionally, the fallback branch in this same conditional tree, really ought to guarantee a scalar replacement and never return raw entity objects.
Remaining tasksTBD
User interface changesTBD
API changesTBD
Data model changesTBD
Add UUID to random tokens
Was looking to generate an random UUID for our use case and was surprised this didn’t exist.
/token/tree route missing proper access permission
After working with tokens, it was discovered that the “Browse available tokens” link can be accessed by anonymous users, exposing site information such as machine names and the site’s structure.
Steps to reproduce- Login as admin
- Open the link of "Browse available tokens" as anonymous user
- See that the page is showing all the information to anonymous users
Adding the necessary permissions to access the “Browse available tokens” page should be fine.
Infinite recursion Error
On Drupal v10.6.1 the Token Service in conjunction with metatag v2 and webform returns infinite loop error on webform save.
The website encountered an unexpected error. Try again later. Error: Maximum call stack size of 8339456 bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion? in Drupal\Core\Entity\ContentEntityBase->Drupal\Core\Entity\{closure}() (line 1042 of core/lib/Drupal/Core/Entity/ContentEntityBase.php). array_filter() (Line: 1041) Drupal\Core\Entity\ContentEntityBase->getTranslationLanguages() (Line: 97) Drupal\Core\Entity\EntityRepository->getTranslationFromContext() (Line: 1055) Drupal\token\Hook\TokenTokensHooks->fieldTokens() (Line: 82) Drupal\token\Hook\TokenTokensHooks->tokens() (Line: 609) token_tokens() call_user_func_array() (Line: 416) Drupal\Core\Extension\ModuleHandler->Drupal\Core\Extension\{closure}() (Line: 395) Drupal\Core\Extension\ModuleHandler->invokeAllWith() (Line: 415) Drupal\Core\Extension\ModuleHandler->invokeAll() (Line: 368) Drupal\Core\Utility\Token->generate() (Line: 691) Drupal\token\Hook\TokenTokensHooks->tokens() (Line: 609) token_tokens() call_user_func_array() (Line: 416) Drupal\Core\Extension\ModuleHandler->Drupal\Core\Extension\{closure}() (Line: 395) Drupal\Core\Extension\ModuleHandler->invokeAllWith() (Line: 415) Drupal\Core\Extension\ModuleHandler->invokeAll() (Line: 368) Drupal\Core\Utility\Token->generate() (Line: 245) Drupal\Core\Utility\Token->doReplace() (Line: 195) Drupal\Core\Utility\Token->replace() (Line: 152) Drupal\webform\WebformTokenManager->replace() (Line: 171) Drupal\webform\WebformTokenManager->replaceNoRenderContext() (Line: 261) Drupal\webform\Entity\WebformSubmission->label() (Line: 105) Drupal\webform\Controller\WebformSubmissionViewController->title() call_user_func_array() (Line: 58) Drupal\Core\Controller\TitleResolver->getTitle() (Line: 465) Drupal\token\Hook\TokenTokensHooks->tokens() (Line: 609) token_tokens() call_user_func_array() (Line: 416) Drupal\Core\Extension\ModuleHandler->Drupal\Core\Extension\{closure}() (Line: 395) Drupal\Core\Extension\ModuleHandler->invokeAllWith() (Line: 415) Drupal\Core\Extension\ModuleHandler->invokeAll() (Line: 368) Drupal\Core\Utility\Token->generate() (Line: 245) Drupal\Core\Utility\Token->doReplace() (Line: 195) Drupal\Core\Utility\Token->replace() (Line: 66) Drupal\metatag\MetatagToken->replace() (Line: 791) Drupal\metatag\MetatagManager->processTagValue() (Line: 634) Drupal\metatag\MetatagManager->generateRawElements() (Line: 61) Drupal\metatag\Plugin\Field\MetatagEntityFieldItemList::Drupal\metatag\Plugin\Field\{closure}() (Line: 637) Drupal\Core\Render\Renderer->executeInRenderContext() (Line: 48) Drupal\metatag\Plugin\Field\MetatagEntityFieldItemList->computeValue() (Line: 32) Drupal\metatag\Plugin\Field\MetatagEntityFieldItemList->ensureComputedValue() (Line: 43) Drupal\metatag\Plugin\Field\MetatagEntityFieldItemList->getValue() (Line: 723) Drupal\Core\Entity\ContentEntityBase->toArray() (Line: 957) Drupal\webform\Entity\WebformSubmission->toArray() (Line: 324) Drupal\webform\Twig\WebformTwigExtension::buildTwigTemplate() (Line: 267) Drupal\webform\Twig\WebformTwigExtension::renderTwigTemplate() (Line: 61) Drupal\webform\Element\WebformComputedTwig::computeValue() (Line: 320) Drupal\webform\Plugin\WebformElement\WebformComputedBase->computeValue() (Line: 459) Drupal\webform\Entity\WebformSubmission->getData() (Line: 1483) Drupal\webform\WebformSubmissionStorage->loadData() (Line: 182) Drupal\webform\WebformSubmissionStorage->doLoadMultiple() (Line: 312) Drupal\Core\Entity\EntityStorageBase->loadMultiple() (Line: 183) Drupal\Core\Entity\EntityRepository->getCanonicalMultiple() (Line: 175) Drupal\Core\Entity\EntityRepository->getCanonical() (Line: 134) Drupal\Core\ParamConverter\EntityConverter->convert() (Line: 100) Drupal\Core\ParamConverter\ParamConverterManager->convert() (Line: 45) Drupal\Core\Routing\Enhancer\ParamConversionEnhancer->enhance() (Line: 276) Drupal\Core\Routing\Router->applyRouteEnhancers() (Line: 156) Drupal\Core\Routing\Router->matchRequest() (Line: 491) Drupal\Core\Url::createFromRequest() (Line: 49) token_url_query_tokens() call_user_func_array() (Line: 416) Drupal\Core\Extension\ModuleHandler->Drupal\Core\Extension\{closure}() (Line: 395) Drupal\Core\Extension\ModuleHandler->invokeAllWith() (Line: 415) Drupal\Core\Extension\ModuleHandler->invokeAll() (Line: 368) Drupal\Core\Utility\Token->generate() (Line: 245) Drupal\Core\Utility\Token->doReplace() (Line: 195) Drupal\Core\Utility\Token->replace() (Line: 66) Drupal\metatag\MetatagToken->replace() (Line: 791) Drupal\metatag\MetatagManager->processTagValue() (Line: 634) Drupal\metatag\MetatagManager->generateRawElements() (Line: 61) Drupal\metatag\Plugin\Field\MetatagEntityFieldItemList::Drupal\metatag\Plugin\Field\{closure}() (Line: 637) Drupal\Core\Render\Renderer->executeInRenderContext() (Line: 48) Drupal\metatag\Plugin\Field\MetatagEntityFieldItemList->computeValue() (Line: 32) Drupal\metatag\Plugin\Field\MetatagEntityFieldItemList->ensureComputedValue() (Line: 43) Drupal\metatag\Plugin\Field\MetatagEntityFieldItemList->getValue() (Line: 723) Drupal\Core\Entity\ContentEntityBase->toArray() (Line: 957) Drupal\webform\Entity\WebformSubmission->toArray() (Line: 324) Drupal\webform\Twig\WebformTwigExtension::buildTwigTemplate() (Line: 267) Drupal\webform\Twig\WebformTwigExtension::renderTwigTemplate() (Line: 61) Drupal\webform\Element\WebformComputedTwig::computeValue() (Line: 320) Drupal\webform\Plugin\WebformElement\WebformComputedBase->computeValue() (Line: 459) Drupal\webform\Entity\WebformSubmission->getData() (Line: 1483) Drupal\webform\WebformSubmissionStorage->loadData() (Line: 182) Drupal\webform\WebformSubmissionStorage->doLoadMultiple() (Line: 312) Drupal\Core\Entity\EntityStorageBase->loadMultiple() (Line: 183) Drupal\Core\Entity\EntityRepository->getCanonicalMultiple() (Line: 175) Drupal\Core\Entity\EntityRepository->getCanonical() (Line: 134) Drupal\Core\ParamConverter\EntityConverter->convert() (Line: 100) Drupal\Core\ParamConverter\ParamConverterManager->convert() (Line: 45) Drupal\Core\Routing\Enhancer\ParamConversionEnhancer->enhance() (Line: 276) Drupal\Core\Routing\Router->applyRouteEnhancers() (Line: 156) Drupal\Core\Routing\Router->matchRequest() (Line: 491) Drupal\Core\Url::createFromRequest() (Line: 49) token_url_query_tokens() call_user_func_array() (Line: 416) Drupal\Core\Extension\ModuleHandler->Drupal\Core\Extension\{closure}() (Line: 395) Drupal\Core\Extension\ModuleHandler->invokeAllWith() (Line: 415) Drupal\Core\Extension\ModuleHandler->invokeAll() (Line: 368) Drupal\Core\Utility\Token->generate() (Line: 245) Drupal\Core\Utility\Token->doReplace() (Line: 195) Drupal\Core\Utility\Token->replace() (Line: 66) Drupal\metatag\MetatagToken->replace() (Line: 791) Drupal\metatag\MetatagManager->processTagValue() (Line: 634) Drupal\metatag\MetatagManager->generateRawElements() (Line: 61) Drupal\metatag\Plugin\Field\MetatagEntityFieldItemList::Drupal\metatag\Plugin\Field\{closure}() (Line: 637) Drupal\Core\Render\Renderer->executeInRenderContext() (Line: 48) Drupal\metatag\Plugin\Field\MetatagEntityFieldItemList->computeValue() (Line: 32) Drupal\metatag\Plugin\Field\MetatagEntityFieldItemList->ensureComputedValue() (Line: 43) Drupal\metatag\Plugin\Field\MetatagEntityFieldItemList->getValue() (Line: 723) Drupal\Core\Entity\ContentEntityBase->toArray() (Line: 957) Drupal\webform\Entity\WebformSubmission->toArray() (Line: 324) Drupal\webform\Twig\WebformTwigExtension::buildTwigTemplate() (Line: 267) Drupal\webform\Twig\WebformTwigExtension::renderTwigTemplate() (Line: 61) Drupal\webform\Element\WebformComputedTwig::computeValue() (Line: 320) Drupal\webform\Plugin\WebformElement\WebformComputedBase->computeValue() (Line: 459) Drupal\webform\Entity\WebformSubmission->getData() (Line: 1483) Drupal\webform\WebformSubmissionStorage->loadData() (Line: 182) Drupal\webform\WebformSubmissionStorage->doLoadMultiple() (Line: 312) Drupal\Core\Entity\EntityStorageBase->loadMultiple() (Line: 183) Drupal\Core\Entity\EntityRepository->getCanonicalMultiple() (Line: 175) Drupal\Core\Entity\EntityRepository->getCanonical() (Line: 134) Drupal\Core\ParamConverter\EntityConverter->convert() (Line: 100) Drupal\Core\ParamConverter\ParamConverterManager->convert() (Line: 45) Drupal\Core\Routing\Enhancer\ParamConversionEnhancer->enhance() (Line: 276) Drupal\Core\Routing\Router->applyRouteEnhancers() (Line: 156) Drupal\Core\Routing\Router->matchRequest() (Line: 491) Drupal\Core\Url::createFromRequest() (Line: 49) token_url_query_tokens() call_user_func_array() (Line: 416) Drupal\Core\Extension\ModuleHandler->Drupal\Core\Extension\{closure}() (Line: 395) Drupal\Core\Extension\ModuleHandler->invokeAllWith() (Line: 415) Drupal\Core\Extension\ModuleHandler->invokeAll() (Line: 368) Drupal\Core\Utility\Token->generate() (Line: 245) Drupal\Core\Utility\Token->doReplace() (Line: 195) Drupal\Core\Utility\Token->replace() (Line: 66) Drupal\metatag\MetatagToken->replace() (Line: 791) Drupal\metatag\MetatagManager->processTagValue() (Line: 634) Drupal\metatag\MetatagManager->generateRawElements() (Line: 61) Drupal\metatag\Plugin\Field\MetatagEntityFieldItemList::Drupal\metatag\Plugin\Field\{closure}() (Line: 637) Drupal\Core\Render\Renderer->executeInRenderContext() (Line: 48) Drupal\metatag\Plugin\Field\MetatagEntityFieldItemList->computeValue() (Line: 32) Drupal\metatag\Plugin\Field\MetatagEntityFieldItemList->ensureComputedValue() (Line: 43) Drupal\metatag\Plugin\Field\MetatagEntityFieldItemList->getValue() (Line: 723) Drupal\Core\Entity\ContentEntityBase->toArray() (Line: 957) Drupal\webform\Entity\WebformSubmission->toArray() (Line: 324) Drupal\webform\Twig\WebformTwigExtension::buildTwigTemplate() (Line: 267) Drupal\webform\Twig\WebformTwigExtension::renderTwigTemplate() (Line: 61) Drupal\webform\Element\WebformComputedTwig::computeValue() (Line: 320) Drupal\webform\Plugin\WebformElement\WebformComputedBase->computeValue() (Line: 459) Drupal\webform\Entity\WebformSubmission->getData() (Line: 1483) Drupal\webform\WebformSubmissionStorage->loadData() (Line: 182) Drupal\webform\WebformSubmissionStorage->doLoadMultiple() (Line: 312) Drupal\Core\Entity\EntityStorageBase->loadMultiple() (Line: 183) Drupal\Core\Entity\EntityRepository->getCanonicalMultiple() (Line: 175) Drupal\Core\Entity\EntityRepository->getCanonical() (Line: 134) Drupal\Core\ParamConverter\EntityConverter->convert() (Line: 100) Drupal\Core\ParamConverter\ParamConverterManager->convert() (Line: 45) Drupal\Core\Routing\Enhancer\ParamConversionEnhancer->enhance() (Line: 276) Drupal\Core\Routing\Router->applyRouteEnhancers() (Line: 156) Drupal\Core\Routing\Router->matchRequest() (Line: 491) Drupal\Core\Url::createFromRequest() (Line: 49) token_url_query_tokens() call_user_func_array() (Line: 416) Drupal\Core\Extension\ModuleHandler->Drupal\Core\Extension\{closure}() (Line: 395) Drupal\Core\Extension\ModuleHandler->invokeAllWith() (Line: 415) Drupal\Core\Extension\ModuleHandler->invokeAll() (Line: 368) Drupal\Core\Utility\Token->generate() (Line: 245) Drupal\Core\Utility\Token->doReplace() (Line: 195) Drupal\Core\Utility\Token->replace() (Line: 66) Drupal\metatag\MetatagToken->replace() (Line: 791) Drupal\metatag\MetatagManager->processTagValue() (Line: 634) Drupal\metatag\MetatagManager->generateRawElements() (Line: 61) Drupal\metatag\Plugin\Field\MetatagEntityFieldItemList::Drupal\metatag\Plugin\Field\{closure}() (Line: 637) Drupal\Core\Render\Renderer->executeInRenderContext() (Line: 48) Drupal\metatag\Plugin\Field\MetatagEntityFieldItemList->computeValue() (Line: 32) Drupal\metatag\Plugin\Field\MetatagEntityFieldItemList->ensureComputedValue() (Line: 43) Drupal\metatag\Plugin\Field\MetatagEntityFieldItemList->getValue() (Line: 723) Drupal\Core\Entity\ContentEntityBase->toArray() (Line: 957) Drupal\webform\Entity\WebformSubmission->toArray() (Line: 324) Drupal\webform\Twig\WebformTwigExtension::buildTwigTemplate() (Line: 267) Drupal\webform\Twig\WebformTwigExtension::renderTwigTemplate() (Line: 61) Drupal\webform\Element\WebformComputedTwig::computeValue() (Line: 320) Drupal\webform\Plugin\WebformElement\WebformComputedBase->computeValue() (Line: 459) Drupal\webform\Entity\WebformSubmission->getData() (Line: 1483) Drupal\webform\WebformSubmissionStorage->loadData() (Line: 182) Drupal\webform\WebformSubmissionStorage->doLoadMultiple() (Line: 312) Drupal\Core\Entity\EntityStorageBase->loadMultiple() (Line: 183) Drupal\Core\Entity\EntityRepository->getCanonicalMultiple() (Line: 175) Drupal\Core\Entity\EntityRepository->getCanonical() (Line: 134) Drupal\Core\ParamConverter\EntityConverter->convert() (Line: 100) Drupal\Core\ParamConverter\ParamConverterManager->convert() (Line: 45) Drupal\Core\Routing\Enhancer\ParamConversionEnhancer->enhance() (Line: 276) Drupal\Core\Routing\Router->applyRouteEnhancers() (Line: 156) Drupal\Core\Routing\Router->matchRequest() (Line: 491) Drupal\Core\Url::createFromRequest() (Line: 49) token_url_query_tokens()InvalidArgumentException when adding menu link to new node with content moderation
When creating a new node with a menu link while using content moderation, an `InvalidArgumentException` is thrown:
InvalidArgumentException: The entity URI 'entity:node/' is invalid. You must specify the entity id in the URL. e.g., entity:node/1 for loading the canonical path to node entity with id 1.
The issue affects non-admin users who save nodes.
1. Enable the Content Moderation module
2. Create a workflow with a default state that has `default_revision: false` (e.g., "Draft")
3. Apply the workflow to a content type (e.g., "Page")
4. Log in as a non-admin user with appropriate permissions (e.g., editor role)
5. Create a new node of that content type
6. Check "Provide a menu link" and fill in the menu link details
7. Save the node as "Draft"
8. **Result:** `InvalidArgumentException` is thrown
Add a check for `$node->id()` before attempting to use it in `token_node_menu_link_submit()`:
Remaining tasks User interface changes API changes Data model changesUpgrade to Drupal 11.3.2. Another Unexpected error encountered
Problem with another web site after upgrading it to 11.3.2
Other upgrades applied at te same time :
mimemail
token
solo utilities
solo theme
I also have applied the patch in ThemeRegistry.php
+#3564510: TypeError: Drupal\Core\Utility\ThemeRegistry::getGlobalPreprocess(): Return value must be of type array
When I tried to run update.php I got the "unexpected error" message.
Now when I try to access to the site, I also get the "unexpected error" message.
This is what is reported in the web server logs.
[Sun Jan 11 14:31:54 2026] [X-OVHRequest-Id: 8dacd6a65072552bff3f2a8c83f6b6c0] [error] [client 2a01:cb10:873:e700:f13a:3e7a:afda:de34:0] [host www.tribupierre.net] AH10131: FastCGI: server "/homez.2186/tribupv/www/index.php" stderr: PHP message: Uncaught PHP Exception ArgumentCountError: "Too few arguments to function Drupal\\token\\Hook\\TokenHooks::__construct(), 0 passed in /home/tribupv/www/core/lib/Drupal/Core/DependencyInjection/ClassResolver.php on line 39 and exactly 3 expected" at /home/tribupv/www/modules/token/src/Hook/TokenHooks.php line 22
[Sun Jan 11 14:32:10 2026] [X-OVHRequest-Id: 4e9f357c081606bed8f2b04d86c9165c] [error] [client 2a01:cb10:873:e700:f13a:3e7a:afda:de34:0] [host www.tribupierre.net] AH10131: FastCGI: server "/homez.2186/tribupv/www/index.php" stderr: PHP message: Uncaught PHP Exception ArgumentCountError: "Too few arguments to function Drupal\\token\\Hook\\TokenHooks::__construct(), 0 passed in /home/tribupv/www/core/lib/Drupal/Core/DependencyInjection/ClassResolver.php on line 39 and exactly 3 expected" at /home/tribupv/www/modules/token/src/Hook/TokenHooks.php line 22
[Sun Jan 11 14:32:30 2026] [X-OVHRequest-Id: 16772be0668b5f8c5b710fb634d10bdd] [error] [client 2a01:cb10:873:e700:f13a:3e7a:afda:de34:0] [host www.tribupierre.net] AH10131: FastCGI: server "/homez.2186/tribupv/www/index.php" stderr: PHP message: Uncaught PHP Exception ArgumentCountError: "Too few arguments to function Drupal\\token\\Hook\\TokenHooks::__construct(), 0 passed in /home/tribupv/www/core/lib/Drupal/Core/DependencyInjection/ClassResolver.php on line 39 and exactly 3 expected" at /home/tribupv/www/modules/token/src/Hook/TokenHooks.php line 22
Thanks for your help.
Steps to reproduce Proposed resolution Remaining tasks User interface changes Introduced terminology API changes Data model changes Release notes snippetYou have requested a non-existent service "Drupal\\token\\Hook\\TokenHooks"
After update from 1.16 to 1.17, broke the site
Debuging the message in log server, appear a message:
Got error 'PHP message: Uncaught PHP Exception Symfony\\Component\\DependencyInjection\\Exception\\ServiceNotFoundException: "You have requested a non-existent service "Drupal\\token\\Hook\\TokenHooks".
Drupal 10.5.7
Token 1.16
Revert the update to 1.16
Remaining tasks User interface changes API changes Data model changesDeprecated function: Case statements followed by a semicolon (;) are deprecated, use a colon (:) instead
In the `token.tokens.inc` file at line 806 (see also https://git.drupalcode.org/project/token/-/blob/8.x-1.16/token.tokens.in...) the last `case` statement in the `switch` is being terminated using a semicolon (;) instead of a colon (:). Besides the fact that this was probably a typo, terminating `case` statements with a semicolon has been deprecated in PHP 8.5.
Proposed resolutionThe semicolon in https://git.drupalcode.org/project/token/-/blob/8.x-1.16/token.tokens.in... should be replaced with a colon to ensure compatibility with PHP 8.5 and later PHP versions.