[Bug]: v3 dynamic configurator reads the wrong version key and cannot handle empty match
- Dominant language
- Go
- Stars
- 5k
- Forks
- 1k
- Avg merge
- 2d 8h
- Merged PRs (30d)
- 31
Description
## What happened?
A standard v3 dynamic configurator rule cannot reliably execute the v3 matching path.
Expected:
- The rule-level YAML field `configVersion: v3.0` selects `configureIfMatchV3`.
- An omitted match or `match: {}` means match-all.
- A partial match evaluates only the dimensions explicitly configured.
- Matching parameters such as `loadbalance` are applied to the target URL.
Actual:
- `DefaultConfigurationParser` writes the rule version to the generated URL as `configVersion`.
- `overrideConfigurator` reads `constant.ConfigVersionKey`, whose value is `config-center.configVersion` and belongs to the config-center component parameter namespace.
- The version lookup therefore returns empty and the standard v3 rule falls into `configureDeprecated`, bypassing v3 match semantics. Simple rules may still appear to work through the deprecated path, producing a false-positive integration result.
- When the v3 path is reached, an omitted or empty `ConditionMatch` contains nil pointers. `ConditionMatch.IsMatch` dereferences `Address`, `ProviderAddress`, `Service`, and `App` unconditionally, so match-all and partial matches can panic before parameters are applied.
## Configuration contract evidence
The rule contract consistently uses `configVersion`:
- Dubbo Admin traffic-rule protobufs, API models, codecs, YAML editors, and validation use `configVersion`.
- Dubbo-Go `ConfiguratorConfig` maps its `ConfigVersion` field to the YAML key `configVersion`.
- `DefaultConfigurationParser` serializes the parsed value into configurator URLs as `configVersion`.
- Condition, Tag, Script, and Affinity rule configurations use the same rule-level spelling.
- Existing parser and configurator tests also construct or assert URLs with `configVersion`.
No equivalent traffic-rule model, codec, YAML document, parser, or Admin API emits `config-center.configVersion`. In the affected rule path, that spelling appears only through `constant.ConfigVersionKey` and the configurator lookup that reused it.
The namespaced value belongs to a different domain. It was introduced when config-center component parameters such as `namespace`, `timeout`, and `username` were renamed to `config-center.namespace`, `config-center.timeout`, and `config-center.username`. `ConfigVersionKey` was namespaced in the same batch. The dynamic configurator continued reusing that component constant even though its rule schema remained `configVersion`.
## Affected chain and nodes
For an application-scoped rule, Admin stores the YAML at a configuration-center node such as:
```text
/dubbo/config/dubbo/.configurators
```
The E2E node is:
```text
/dubbo/config/dubbo/router-rule-e2e-dynamic-consumer.configurators
```
The complete affected chain is:
```text
Admin Dynamic Config form/YAML
-> Console API request with configVersion
-> ZooKeeper .configurators node containing configVersion: v3.0
-> dubbo-go configuration listener
-> DefaultConfigurationParser.ParseToUrls
-> appItemToUrls/serviceItemToUrls creates an override URL with configVersion=v3.0
-> overrideConfigurator.Configure reads the version and selects a matching path
-> configureIfMatchV3
-> ConditionMatch.IsMatch
-> parameters are copied to the target consumer/provider URL
-> directory/load balancer uses the resulting URL
-> provider invocation behavior changes
```
Admin persistence and the ZooKeeper node are correct. The first failure occurs after the node is read: `overrideConfigurator.Configure` looks up `config-center.configVersion`, misses the parser-generated `configVersion`, and selects the deprecated path. Correcting that lookup exposes the second failure at `ConditionMatch.IsMatch`, before parameters can be copied to the target URL.
Consequently, an Admin response, a correct ZooKeeper node, and even a configuration-change listener event are not sufficient evidence that the v3 rule is active. The final URL parameters and invocation behavior must also be checked.
## How can we reproduce it?
Use a v3 application-scoped dynamic configuration such as:
```yaml
configVersion: v3.0
enabled: true
key: demo-consumer
scope: application
configs:
- side: consumer
match: {}
enabled: true
parameters:
loadbalance: roundrobin
```
1. Save the rule through Dubbo Admin and confirm the `.configurators` ZooKeeper node contains the YAML above.
2. Parse the YAML with `DefaultConfigurationParser.ParseToUrls`.
3. Observe that the generated configurator URL contains `configVersion=v3.0`.
4. Pass that URL to `overrideConfigurator.Configure`.
5. The configurator looks for `config-center.configVersion`, does not recognize the v3 rule, and enters the deprecated path.
6. If version dispatch is corrected independently, evaluating the empty match reaches nil matcher fields and can panic.
A non-matching application constraint also demonstrates the incorrect dispatch: the parameter is applied by the deprecated path even though the v3 match should reject the target URL.
Without both fixes, an end-to-end test cannot prove the intended chain:
```text
Admin rule -> ZooKeeper node -> v3 parser/configurator -> target URL parameters -> invocation behavior
```
## Environment
- dubbo-go: `develop` at `a10df2f7`
- Go: `go1.25.5`
- OS: Windows amd64; the issue is platform-independent
- Config center: ZooKeeper
Contributor guide
Assessment
This issue has not been assessed yet.