codeAnqiang-ma opened a new pull request, #3655:
URL: https://github.com/apache/dubbo-go/pull/3655
### Description
Fixes #3654
Over the Triple (non-gRPC) unary transport, a server-returned `CodeBizError`
(17) reaches the client as `CodeUnknown` (2); the gRPC transport in the same
package preserves it. Downstream, `failover.isBizError` stops recognizing
business errors and retries them (default up to 3 attempts, so non-idempotent
calls run repeatedly), and `metrics/rpc` counts them as unknown.
**Root cause.** `tripleWireError.asError()` (`protocol_triple.go:694`)
clamps any code outside `[minCode, maxCode]` = `[1,16]` to `CodeUnknown`. That
clamp comes from connect-go, which only defines codes 1..16; `CodeBizError =
17` is a dubbo-go extension and `maxCode` was never updated. `code.go`
deliberately supports such codes — the `UnmarshalText` branch commented
*"Ensure that non-canonical codes round-trip through MarshalText and
UnmarshalText"* keeps out-of-range codes for exactly this reason. `asError()`
then discards what `UnmarshalText` just preserved.
**Fix.** Exempt `CodeBizError` from the clamp (one line), plus
`TestBizErrorCodePreservedAcrossProtocols`: a real `httptest` server whose
handler returns `NewError(CodeBizError, ...)`, asserting the client-visible
code over both transports. Before the fix the `triple` subtest fails (`got:
unknown, want: code_17`) while `grpc` passes; after, both pass.
<details>
<summary>Why not raise <code>maxCode</code> to <code>CodeBizError</code>
instead</summary>
That breaks the round-trip. The `UnmarshalText` fallback only keeps codes
*outside* `[minCode, maxCode]`:
```go
if err == nil && (code < uint64(minCode) || code > uint64(maxCode)) {
*c = Code(code)
return nil
}
```
With `maxCode = CodeBizError`, the string `code_17` no longer satisfies that
condition and falls through to `invalid code %q`. Making it work needs a
canonical string for `CodeBizError` in both `String()` and `UnmarshalText`,
which changes the wire representation of the code. The clamp exemption keeps
the existing wire format and touches one line.
</details>
<details>
<summary>Test output (before / after)</summary>
Before the fix — only `protocol_triple.go` reverted, test unchanged:
```
$ go test ./protocol/triple/triple_protocol/ -run
TestBizErrorCodePreservedAcrossProtocols -v
=== NAME TestBizErrorCodePreservedAcrossProtocols/triple
triple_ext_test.go:772:
assertion: assert.Equal
got: unknown
want: code_17
--- FAIL: TestBizErrorCodePreservedAcrossProtocols (0.00s)
--- FAIL: TestBizErrorCodePreservedAcrossProtocols/triple (0.01s)
--- PASS: TestBizErrorCodePreservedAcrossProtocols/grpc (0.01s)
FAIL dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol 4.304s
```
After:
```
--- PASS: TestBizErrorCodePreservedAcrossProtocols (0.00s)
--- PASS: TestBizErrorCodePreservedAcrossProtocols/triple (0.00s)
--- PASS: TestBizErrorCodePreservedAcrossProtocols/grpc (0.02s)
ok dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol 0.970s
```
Existing tests, including the packages that consume the code:
```
$ go test ./protocol/triple/... ./cluster/cluster/failover/...
./metrics/rpc/...
ok dubbo.apache.org/dubbo-go/v3/cluster/cluster/failover 1.675s
ok dubbo.apache.org/dubbo-go/v3/metrics/rpc 2.234s
ok dubbo.apache.org/dubbo-go/v3/protocol/triple 5.790s
ok dubbo.apache.org/dubbo-go/v3/protocol/triple/health 1.687s
ok dubbo.apache.org/dubbo-go/v3/protocol/triple/openapi 2.138s
ok dubbo.apache.org/dubbo-go/v3/protocol/triple/reflection 2.667s
ok dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol 18.123s
```
`go vet ./protocol/triple/triple_protocol/...` and `gofmt -l` are both clean.
Not run locally: the full `make test` and the integration suite (they need
ZooKeeper / Nacos / etcd / Docker, which I don't have set up), and
golangci-lint. Leaving those to CI.
</details>
### Checklist
- [x] I confirm the target branch is `develop`
- [x] Code has passed local testing
- [x] I have added tests that prove my fix is effective or that my feature
works
_Assisted-by: Cursor (Claude Opus 5). Reproduced, reviewed and tested
locally by the author._
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]