grpc/grpc-go · critical

ClientConn's authority from transport creds

Error message

ClientConn's authority from transport creds %q and dial option %q don't match

What it means

initAuthority determines the channel authority from three sources: WithAuthority dial option, transport credentials' ServerName, and the dial target endpoint. If both WithAuthority and the credentials specify a non-empty server name and they disagree, NewClient/Dial fails (clientconn.go:1958-1959). Mismatched authority would break TLS verification and routing, so it is rejected up front.

Solutions

  1. Make WithAuthority and the credentials' ServerName identical.
  2. Drop one of them: use only transport credentials to derive authority, or only WithAuthority, so there is no value to disagree.
  3. If you need to override, call OverrideServerName on the credentials to match the WithAuthority value.

Example fix

// before
creds := credentials.NewClientTLSFromCert(caPool, "server.example")
cc, err := grpc.NewClient(addr, grpc.WithTransportCredentials(creds), grpc.WithAuthority("other.example"))
// after
cc, err := grpc.NewClient(addr, grpc.WithTransportCredentials(creds)) // authority derived from creds
// or, if overriding:
creds := credentials.NewClientTLSFromCert(caPool, "override.example")
cc, err := grpc.NewClient(addr, grpc.WithTransportCredentials(creds), grpc.WithAuthority("override.example"))
Defensive patterns

Strategy: validation

Validate before calling

func authoritiesAgree(creds credentials.TransportCredentials, authority string) error {
	if creds == nil { return nil }
	name := creds.Info().ServerName
	if name != "" && authority != "" && name != authority {
		return fmt.Errorf("creds ServerName %q != WithAuthority %q", name, authority)
	}
	return nil
}

Try / catch

cc, err := grpc.NewClient(target, grpc.WithTransportCredentials(creds), grpc.WithAuthority(auth))
if err != nil && strings.Contains(err.Error(), "authority from transport creds") {
    // reconcile creds.ServerName and the WithAuthority value
}

Prevention

When it happens

Trigger: Combining grpc.WithAuthority("a.example") with transport credentials whose ServerName is "b.example" (e.g., credentials.NewClientTLSFromFile or NewTLS with a different server name, possibly after OverrideServerName).

Common situations: Setting WithAuthority for SNI/routing while the TLS creds carry a different server name; copy-paste of dial options from another target; rotating certs/target and updating only one of the two.

Related errors


AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11). Data as JSON: /api/errors/cf27f0ac6663cc87. Report an issue: GitHub.

Appendix: 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 0c51461d27)