apache / apache/dubbo-go

[Bug]: v3 dynamic configurator reads the wrong version key and cannot handle empty match

Open
#3,661 3 comments 0 reactions 1 assignee Claimed by @xiaobaicai66695 View on GitHub
☢️ Bug 3.3.3
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.