grpc/grpc-go · error
scheme is not supported: %q. Only http(s) is supported
Error message
scheme is not supported: %q. Only http(s) is supported
What it means
Returned by validateOptions in sts/sts.go:220 when the parsed TokenExchangeServiceURI's scheme is neither http nor https. STS token exchange (RFC 8693) is performed over a plain HTTP request, so any other scheme (grpc://, dns://, unix:) is rejected at construction time.
Source
Thrown at credentials/sts/sts.go:220
},
},
}
}
// 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
}
// cachedMetadata returns the cached metadata provided it is not going to
// expire anytime soon.
//
// Caller must hold c.mu.
func (c *callCreds) cachedMetadata() map[string]string {
now := time.Now()
// If the cached token has not expired and the lifetime remaining on thatView on GitHub (pinned to 03255a9237)
Solutions
- Set TokenExchangeServiceURI to a fully-qualified http(s) URL (e.g. https://sts.googleapis.com/v1/token).
- Regenerate/fix the xDS bootstrap so the token_exchange_service_uri field is an http(s) URL.
- If a non-TLS endpoint is acceptable for testing, use http:// explicitly.
Example fix
// before
opts := sts.Options{TokenExchangeServiceURI: "grpc://sts.example.com:443", ...}
// after
opts := sts.Options{TokenExchangeServiceURI: "https://sts.example.com/v1/token", ...} Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(opts.TokenExchangeServiceURI)
if err != nil { return fmt.Errorf("bad STS URI: %w", err) }
if u.Scheme != "http" && u.Scheme != "https" {
return fmt.Errorf("STS URI must be http(s), got %q", u.Scheme)
}
stsCreds, err := sts.NewCredentials(opts)
if err != nil { return err } Try / catch
stsCreds, err := sts.NewCredentials(opts)
if err != nil {
if strings.Contains(err.Error(), "scheme is not supported") {
// fix TokenExchangeServiceURI to an http(s) URL
}
return err
} Prevention
- Always store the STS endpoint as a full http(s) URL in config/bootstrap.
- Do not confuse the gRPC server target with the STS token endpoint.
- Validate the scheme at config-load time, not just at dial time.
When it happens
Trigger: Setting Options.TokenExchangeServiceURI to a gRPC target, a dns:/// resolver URI, a bare hostname without scheme, or any non-http(s) URL when calling sts.NewCredentials.
Common situations: Confusing the STS endpoint URL with the gRPC server target; xDS bootstrap generated with a grpc:// or xds:// scheme for the token exchange; omitting the https:// prefix.
Related errors
- tokenFilePath cannot be empty
- failed to create http request: %v
- empty accessToken in response (%v)
- meshca: unsupported config type: %T
- empty token_exchange_service_uri in options
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/6b334513eeabc381.
Report an issue: GitHub.