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 that

View on GitHub (pinned to 03255a9237)

Solutions

  1. Set TokenExchangeServiceURI to a fully-qualified http(s) URL (e.g. https://sts.googleapis.com/v1/token).
  2. Regenerate/fix the xDS bootstrap so the token_exchange_service_uri field is an http(s) URL.
  3. 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

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


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/6b334513eeabc381. Report an issue: GitHub.