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 (credentials/sts/sts.go:213) when opts.TokenExchangeServiceURI is the empty string. NewCredentials calls validateOptions before building the STS call-credentials instance, so this is a hard constructor failure: the STS plugin (RFC 8693 token exchange) cannot know which server to POST the token-exchange request to without a URI, so it refuses to construct.
Source
Thrown at credentials/sts/sts.go:213
func makeHTTPClient(roots *x509.CertPool) httpDoer {
return &http.Client{
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 03255a9237)
Solutions
- Set Options.TokenExchangeServiceURI to the STS endpoint URL before calling NewCredentials.
- Always check the error returned by sts.NewCredentials and fail fast if non-nil.
- Validate the config struct in your own config-loading layer (non-empty + http(s) scheme) before passing it to NewCredentials.
Example fix
// before
c, err := sts.NewCredentials(sts.Options{
SubjectTokenPath: "/var/run/secrets/token",
SubjectTokenType: "urn:ietf:params:oauth:token-type:jwt",
}) // err: empty token_exchange_service_uri
// after
c, 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
// Validate STS Options before constructing credentials.
func validateSTS(o sts.Options) error {
if o.TokenExchangeServiceURI == "" {
return errors.New("TokenExchangeServiceURI is required")
}
if u, err := url.Parse(o.TokenExchangeServiceURI); err != nil || (u.Scheme != "http" && u.Scheme != "https") {
return fmt.Errorf("TokenExchangeServiceURI must be http(s), got %q", o.TokenExchangeServiceURI)
}
if o.SubjectTokenPath == "" {
return errors.New("SubjectTokenPath is required")
}
if o.SubjectTokenType == "" {
return errors.New("SubjectTokenType is required")
}
return nil
}
if err := validateSTS(opts); err != nil { log.Fatal(err) }
c, err := sts.NewCredentials(opts) Try / catch
c, err := sts.NewCredentials(opts)
if err != nil {
// err contains the exact missing-field message; log and abort startup
log.Fatalf("STS credentials invalid: %v", err)
} Prevention
- Load STS config into a typed struct and run a single validate() at startup.
- Always check the error from sts.NewCredentials; never assume success.
- Unit-test your config parser against a golden Options that passes validateOptions.
When it happens
Trigger: Calling sts.NewCredentials(Options{...}) without setting TokenExchangeServiceURI, or with it explicitly empty. Any subsequent code that ignores the returned error and tries to use the nil credentials will then panic.
Common situations: Reading the STS Options from a JSON/env config and the field is absent or misnamed; copy-pasting a sample that omits the field; refactoring that renamed the struct field; config templating that renders an empty value.
Related errors
- required field SubjectTokenPath is not specified
- required field SubjectTokenType is not specified
- missing fallback credentials
- token file access error
- pemfile: certificate and key file must be in the same direct
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/f1a0f53a45f1b611.
Report an issue: GitHub.