Description
docker compose -f base.yaml -f override.yaml config returns
cycle detected: node at path services.test.other references node at path services.test
When:
- The override file uses an anchor with at least 2 aliases
- Among the alias services, one name is a dot-delimited prefix of another (e.g.
test and test.other)
There is no actual cycle — the services are independent and simply share configuration via a YAML anchor.
Service names without dots, or dotted names that are not prefixes of other service names, are unaffected.
Steps To Reproduce
A minimal example involves two service names where one is a dot-delimited prefix of the other, and both are aliases of the same anchor in the override file, and we're merging service definitions from override files.
docker-compose.yaml:
services:
test:
image: alpine
test.unit:
image: alpine
test.other:
image: alpine
override.yaml:
services:
test.unit: &shared {}
test: *shared
test.other: *shared
Run:
docker compose -f docker-compose.yaml -f override.yaml config
Observe:
cycle detected: node at path services.test.other references node at path services.test
I'd expect this to succeed without error, since there is no actual cycle.
Compose Version
Docker Environment
Anything else?
The issue looks to be in compose-go/loader/reset.go, in the checkForCycle and areInDifferentServices functions introduced in compose-spec/compose-go#709.
areInDifferentServices is supposed to allow the same anchor across different services, but it splits the paths on dots to extract the service name — so test.other and test get split into [test, other] and [test] but only the first segment is considered the service name. This trips up the cycle detection as it appears as if we've visited the shared anchor before in the same service, when in fact it's a different service.
Description
docker compose -f base.yaml -f override.yaml configreturnsWhen:
testandtest.other)There is no actual cycle — the services are independent and simply share configuration via a YAML anchor.
Service names without dots, or dotted names that are not prefixes of other service names, are unaffected.
Steps To Reproduce
A minimal example involves two service names where one is a dot-delimited prefix of the other, and both are aliases of the same anchor in the override file, and we're merging service definitions from override files.
docker-compose.yaml:
override.yaml:
Run:
Observe:
I'd expect this to succeed without error, since there is no actual cycle.
Compose Version
Docker Environment
Anything else?
The issue looks to be in
compose-go/loader/reset.go, in thecheckForCycleandareInDifferentServicesfunctions introduced in compose-spec/compose-go#709.areInDifferentServicesis supposed to allow the same anchor across different services, but it splits the paths on dots to extract the service name — sotest.otherandtestget split into [test,other] and [test] but only the first segment is considered the service name. This trips up the cycle detection as it appears as if we've visited the shared anchor before in the same service, when in fact it's a different service.