grpc/grpc-go · error

failed to create http request: %v

Error message

failed to create http request: %v

What it means

Returned by constructRequest in sts/sts.go:291 when http.NewRequestWithContext fails while building the POST to the token-exchange endpoint. NewRequestWithContext fails on a malformed URL (e.g. control characters, bad escaping) or on a nil/invalid context. The wrapped %v is the underlying error.

Source

Thrown at credentials/sts/sts.go:291

		RequestedTokenType: opts.RequestedTokenType,
		SubjectToken:       string(subToken),
		SubjectTokenType:   opts.SubjectTokenType,
	}
	if opts.ActorTokenPath != "" {
		actorToken, err := readActorTokenFrom(opts.ActorTokenPath)
		if err != nil {
			return nil, err
		}
		reqParams.ActorToken = string(actorToken)
		reqParams.ActorTokenType = opts.ActorTokenType
	}
	jsonBody, err := json.Marshal(reqParams)
	if err != nil {
		return nil, err
	}
	req, err := http.NewRequestWithContext(ctx, "POST", opts.TokenExchangeServiceURI, bytes.NewBuffer(jsonBody))
	if err != nil {
		return nil, fmt.Errorf("failed to create http request: %v", err)
	}
	req.Header.Set("Content-Type", "application/json")
	return req, nil
}

func sendRequest(client httpDoer, req *http.Request) ([]byte, error) {
	// http.Client returns a non-nil error only if it encounters an error
	// caused by client policy (such as CheckRedirect), or failure to speak
	// HTTP (such as a network connectivity problem). A non-2xx status code
	// doesn't cause an error.
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}

	// When the http.Client returns a non-nil error, it is the
	// responsibility of the caller to read the response body till an EOF is
	// encountered and to close it.

View on GitHub (pinned to 03255a9237)

Solutions

  1. Sanitize and re-validate TokenExchangeServiceURI with url.ParseRequestURI before calling NewCredentials.
  2. Ensure the context passed into the RPC (and thus GetRequestMetadata) is non-nil and not pre-canceled.
  3. Strip whitespace/control characters from the configured URI.

Example fix

// before
opts := sts.Options{TokenExchangeServiceURI: strings.TrimSpace(rawURI) + "\r\n", ...}

// after
u, err := url.ParseRequestURI(strings.TrimSpace(rawURI))
if err != nil { return err }
opts := sts.Options{TokenExchangeServiceURI: u.String(), ...}
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.ParseRequestURI(strings.TrimSpace(opts.TokenExchangeServiceURI))
if err != nil { return fmt.Errorf("invalid STS request URI: %w", err) }
opts.TokenExchangeServiceURI = u.String()
// also ensure the RPC context passed in is non-nil and not pre-canceled
stsCreds, err := sts.NewCredentials(opts)

Try / catch

if strings.Contains(err.Error(), "failed to create http request") {
    // URI malformed for net/http; sanitize or the context was nil/canceled
}

Prevention

When it happens

Trigger: TokenExchangeServiceURI parses (passes validateOptions) but is structurally invalid for http.NewRequest; the passed context is nil; the URI contains characters the URL parser in NewRequest rejects.

Common situations: A URI that passed url.Parse but trips net/http's stricter validation; a context that was already canceled and somehow nil-wrapped; copy-paste of a URL with embedded credentials or whitespace.

Related errors


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