Problem/Motivation

The DomainPathUniquePathAliasConstraintValidator does not scope its alias uniqueness check to the current domain. When saving a node with a URL alias that also has a domain-specific path alias, the validator queries all path aliases across all domains. This causes a false "The alias is already in use" validation error when the same alias legitimately exists on different domains.
For example: saving a node on domain A with alias /about fails if domain B already has a domain-specific alias /about, even though these are separate domains and the aliases should not conflict.

Steps to reproduce

Set up two domains (e.g. domain_a and domain_b).
Create a node with URL alias /example and assign a domain-specific path for domain_b with alias /example.
Try to save the node.
The validation error "The alias /example is already in use in this language" is triggered, even though the aliases belong to different domains.

Proposed resolution

Add a domain_id condition to the uniqueness query in DomainPathUniquePathAliasConstraintValidator::validate() so that aliases are only checked for uniqueness within the same domain scope:
When the entity has a domain_id, add ->condition('domain_id', $domain_id, '=') to the query.
When the entity has no domain_id (a global alias), add ->notExists('domain_id') so it only checks against other global aliases.
Additionally, use the DomainPathAliasInterface type hint and the hasDomainId() / getDomainId() helper methods instead of accessing the field value directly via $entity->get('domain_id')->getValue().

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

kevzijl created an issue. See original summary.

mably’s picture

Hi @kevzijl, thanks for the catch! We need to fix that ASAP.

Are you preparing an MR or should I make one?

I have some code ready if needed.

mably’s picture

Status: Active » Needs review

Pushed a fix based on your suggestions. Please review.

Problem

The DomainPathUniquePathAliasConstraintValidator does not scope the alias uniqueness query to the current domain. The query only filters by alias + langcode, so it finds matches across all domains. The violation-handling logic then falls through to a generic "already in use" error when domain IDs differ, instead of recognizing that aliases on separate domains should not conflict.

This causes false validation errors like: saving a node on domain A with alias /about fails if domain B already has /about, even though they are on separate domains.

There is also a secondary bug: the original code passes $entity->get('domain_id')->getValue() (an array) directly to the %domain placeholder in the violation message, which causes a TypeError.

Fix

Added domain filtering to the entity query in DomainPathUniquePathAliasConstraintValidator::validate():

  • When the entity has a domain_id: ->condition('domain_id', $entity->getDomainId()) — only match aliases in the same domain
  • When the entity has no domain_id (global alias): ->notExists('domain_id') — only match other global aliases

Also replaced raw $entity->get('domain_id')->getValue() calls with the proper DomainPathAliasInterface helper methods (hasDomainId(), getDomainId()) and updated the @var type hint accordingly.

Test coverage

Added a new Kernel test DomainPathUniqueAliasTest with 6 test methods covering the full uniqueness matrix:

  • testSameAliasOnDifferentDomainsIsAllowed — /about on domain A + /about on domain B → no violation
  • testSameAliasOnSameDomainConflicts — /about on domain A twice → violation ("already in use in this domain")
  • testGlobalAliasDoesNotConflictWithDomainAlias — /about on domain A + global /about → no violation
  • testDomainAliasDoesNotConflictWithGlobalAlias — global /about + /about on domain A → no violation
  • testDuplicateGlobalAliasesConflict — global /about twice → violation ("already in use")
  • testEditingExistingAliasDoesNotSelfConflict — re-validating an existing alias → no violation

Verified the tests catch the original bug: reverting the fix causes 3 failures + 1 error (the TypeError from passing an array to %domain).

mably’s picture

Priority: Normal » Major

  • mably committed 67b9a968 on 2.x
    fix: #3574489 DomainPathUniquePathAliasConstraintValidator does not...
mably’s picture

Status: Needs review » Fixed

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

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