Change record status: 
Introduced in branch: 
3.1.x
Introduced in version: 
3.1.9
Description: 

ECA lets you write a nested token path with dots instead of colons, because TokenDecoratorTrait::normalizeKey() translates . to :. Drupal core never sees such a token: Token::scan() only matches [type:rest], so ECA scans for colon-free tokens itself and resolves them as root-level tokens.

Resolution always worked. Rendering did not. The root-level path only produced a string for scalars, for objects with __toString() and for entities. Every path that resolved to a typed data object - which is most of them - rendered as an empty string, and no replacement was recorded at all.

Before

[foo.bar]            => ''        [foo:bar]       => 'baz'
[pdf.0.fids.0]       => ''        [pdf:0:fids:0]  => '123'
[account.name]       => ''        [account:name]  => 'admin'
[account.name.value] => 'admin'

After

All four render the same as their colon spelling.

Why the old behavior looked arbitrary

[account.name.value] rendered but [account.name] did not, because FieldItemList is a ListInterface and not a ComplexDataInterface, so resolution fell into magic property access and landed on a raw PHP string.

What you need to check

Only models that print a dot-separated token. One that silently produced an empty string now produces a value: conditions comparing such a token against an empty value flip from TRUE to FALSE; templates that tolerated the empty replacement change output. Token: set value is explicitly called out as unaffected, because it already worked - the value was re-wrapped into a DTO, so only direct printing failed.

Impacts: 
Site builders, administrators, editors