grpc/grpc-go · error
empty token_exchange_service_uri in options
Error message
empty token_exchange_service_uri in options
What it means
Returned by sts.validateOptions when Options.TokenExchangeServiceURI is empty. NewCredentials calls validateOptions before constructing the STS call-credential, so this error prevents creating credentials without a token exchange endpoint. The URI is the server that implements RFC 8693 token exchange and is required for the credential to function.
Solutions
- Set Options.TokenExchangeServiceURI to a valid http(s) URI before calling NewCredentials.
- If the URI comes from config/env, validate it is non-empty before passing it to NewCredentials and log a clear error.
- For Google Cloud STS, use the standard endpoint https://sts.googleapis.com/v1/token.
Example fix
// before
creds, err := sts.NewCredentials(sts.Options{}) // empty URI
// after
creds, err := sts.NewCredentials(sts.Options{
TokenExchangeServiceURI: "https://sts.googleapis.com/v1/token",
SubjectTokenPath: "/var/run/secrets/token",
SubjectTokenType: "urn:ietf:params:oauth:token-type:jwt",
}) Defensive patterns
Strategy: validation
Validate before calling
if opts.TokenExchangeServiceURI == "" {
return fmt.Errorf("TokenExchangeServiceURI must be set (e.g., https://sts.googleapis.com/v1/token)")
}
creds, err := sts.NewCredentials(opts) Prevention
- Validate all required STS Options fields before calling NewCredentials.
- Load the URI from a well-known config key and fail fast if missing.
- Use the Google Cloud standard STS endpoint as a documented default.
When it happens
Trigger: Calling sts.NewCredentials(sts.Options{}) or any Options struct where TokenExchangeServiceURI is the zero value (empty string). The field is marked Required in the Options struct documentation.
Common situations: Configuration-driven credential setup where the URI is read from an environment variable, a config file, or a bootstrap file that is missing the key. Developers copy example code and forget to fill in the endpoint. Service-mesh or workload-identity setups where the STS endpoint comes from metadata that was not fetched.
Related errors
- required field SubjectTokenPath is not specified
- required field SubjectTokenType is not specified
- missing fallback credentials
- AuthInfo is nil
- cannot have a leading slash
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/f1a0f53a45f1b611.
Report an issue: GitHub.
Appendix: source
Thrown at credentials/sts/sts.go:220
CheckRedirect: func(*http.Request, []*http.Request) error {
return http.ErrUseLastResponse
},
Timeout: stsRequestTimeout,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: roots,
},
},
}
}
// validateOptions performs the following validation checks on opts:
// - tokenExchangeServiceURI is not empty
// - tokenExchangeServiceURI is a valid URI with a http(s) scheme
// - subjectTokenPath and subjectTokenType are not empty.
func validateOptions(opts Options) error {
if opts.TokenExchangeServiceURI == "" {
return errors.New("empty token_exchange_service_uri in options")
}
u, err := url.Parse(opts.TokenExchangeServiceURI)
if err != nil {
return err
}
if u.Scheme != "http" && u.Scheme != "https" {
return fmt.Errorf("scheme is not supported: %q. Only http(s) is supported", u.Scheme)
}
if opts.SubjectTokenPath == "" {
return errors.New("required field SubjectTokenPath is not specified")
}
if opts.SubjectTokenType == "" {
return errors.New("required field SubjectTokenType is not specified")
}
return nil
}
View on GitHub (pinned to 0c51461d27)