grpc/grpc-go · error
ClientConn's authority from transport creds %q and dial opti
Error message
ClientConn's authority from transport creds %q and dial option %q don't match
What it means
initAuthority (clientconn.go:1953-1959) reads the server name from transport credentials (creds.Info().ServerName) and the value set by the WithAuthority() dial option. If BOTH are non-empty AND they differ, the channel refuses to start because the authority would be ambiguous for TLS SNI and :authority headers.
Source
Thrown at clientconn.go:1959
func (cc *ClientConn) initAuthority() error {
dopts := cc.dopts
// Historically, we had two options for users to specify the serverName or
// authority for a channel. One was through the transport credentials
// (either in its constructor, or through the OverrideServerName() method).
// The other option (for cases where WithInsecure() dial option was used)
// was to use the WithAuthority() dial option.
//
// A few things have changed since:
// - `insecure` package with an implementation of the `TransportCredentials`
// interface for the insecure case
// - WithAuthority() dial option support for secure credentials
authorityFromCreds := ""
if creds := dopts.copts.TransportCredentials; creds != nil && creds.Info().ServerName != "" {
authorityFromCreds = creds.Info().ServerName
}
authorityFromDialOption := dopts.authority
if (authorityFromCreds != "" && authorityFromDialOption != "") && authorityFromCreds != authorityFromDialOption {
return fmt.Errorf("ClientConn's authority from transport creds %q and dial option %q don't match", authorityFromCreds, authorityFromDialOption)
}
endpoint := cc.parsedTarget.Endpoint()
if authorityFromDialOption != "" {
cc.authority = authorityFromDialOption
} else if authorityFromCreds != "" {
cc.authority = authorityFromCreds
} else if auth, ok := cc.resolverBuilder.(resolver.AuthorityOverrider); ok {
cc.authority = auth.OverrideAuthority(cc.parsedTarget)
} else if strings.HasPrefix(endpoint, ":") {
cc.authority = "localhost" + encodeAuthority(endpoint)
} else {
cc.authority = encodeAuthority(endpoint)
}
return nil
}
View on GitHub (pinned to 03255a9237)
Solutions
- Make the WithAuthority() value and the credentials ServerName identical.
- If they must differ legitimately, remove one of them — typically drop WithAuthority and rely on the creds' ServerName.
- Use OverrideServerName on the credentials so there is a single source of truth.
Example fix
// before
creds := credentials.NewTLS(&tls.Config{ServerName: "a.example"})
grpc.WithTransportCredentials(creds), grpc.WithAuthority("b.example")
// after
creds := credentials.NewTLS(&tls.Config{ServerName: "a.example"})
grpc.WithTransportCredentials(creds) // authority derived from creds Defensive patterns
Strategy: validation
Validate before calling
// Ensure authority and credential ServerName agree before constructing the channel.
func authoritiesAgree(serverName, authority string) bool {
if serverName == "" || authority == "" { return true }
return serverName == authority
} Prevention
- Set authority in exactly one place: either credentials ServerName or WithAuthority, not both.
- Add a startup assertion that the two match if both are configured.
- Document the intended authority source for each connection target.
When it happens
Trigger: Combining credentials.NewTLS credsWithServerName(...) (or OverrideServerName) with grpc.WithAuthority("...") where the two strings disagree. NewClient/Dial fails before connecting.
Common situations: Setting WithAuthority for a proxy but leaving the TLS creds pointed at the real backend name; refactoring that updated one and not the other; connecting through an LB with a different authority than the cert SAN.
Related errors
- %s: %v
- failed to build credentials bundle from bootstrap for %q: %v
- pemfile: certificate and key file must be in the same direct
- provider instance is closed
- xds: CertificateProvider to fetch trusted roots is missing,
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/cf27f0ac6663cc87.
Report an issue: GitHub.