jaegertracing/jaeger · error

no http.RoundTripper provided

Error message

no http.RoundTripper provided

What it means

RoundTrip returns this error when auth.RoundTripper has a nil inner Transport. The wrapper exists to inject an Authorization header into outbound requests and delegates the actual request to the embedded http.RoundTripper, so a nil one is unusable.

Source

Thrown at internal/auth/transport.go:37

	TokenFn func() string

	// FromCtx extracts token from context
	FromCtx func(context.Context) (string, bool)
}

// RoundTripper wraps another http.RoundTripper and injects
// an authentication header with  token into requests.
type RoundTripper struct {
	// Transport is the underlying http.RoundTripper being wrapped. Required.
	Transport http.RoundTripper
	Auths     []Method
}

// RoundTrip injects the outbound Authorization header with the
// token provided in the inbound request.
func (tr RoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
	if tr.Transport == nil {
		return nil, errors.New("no http.RoundTripper provided")
	}

	req := r.Clone(r.Context())

	for _, auth := range tr.Auths {
		token := ""

		// Get token from context if available
		if auth.FromCtx != nil {
			if t, ok := auth.FromCtx(r.Context()); ok {
				token = t
			}
		}

		// Fall back to TokenFn if no token from context
		if token == "" && auth.TokenFn != nil {
			token = auth.TokenFn()
		}

View on GitHub (pinned to 806f444784)

Solutions

  1. Set the Transport field explicitly, e.g. auth.RoundTripper{Transport: http.DefaultTransport, Auths: ...}
  2. Or wrap an existing client: base := http.DefaultTransport; client.Transport = auth.RoundTripper{Transport: base, Auths: auths}
  3. Add a constructor or init-time check that panics/errors on nil Transport before the client is used

Example fix

// before
client := &http.Client{
  Transport: auth.RoundTripper{Auths: auths},
}
// after
client := &http.Client{
  Transport: auth.RoundTripper{Transport: http.DefaultTransport, Auths: auths},
}
Defensive patterns

Strategy: validation

Validate before calling

rt := auth.RoundTripper{Transport: http.DefaultTransport, Auths: auths}
if rt.Transport == nil {
    return errors.New("auth.RoundTripper requires a non-nil Transport")
}

Type guard

func validRoundTripper(rt auth.RoundTripper) bool {
    return rt.Transport != nil
}

Try / catch

resp, err := client.Do(req)
if err != nil {
    if strings.Contains(err.Error(), "no http.RoundTripper provided") {
        return fmt.Errorf("set RoundTripper.Transport: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Constructing auth.RoundTripper{Auths: ...} without setting Transport and then using it in an http.Client (Transport field); unlike http.Transport, the wrapper does not default to http.DefaultTransport.

Common situations: Hand-building the struct literal in tests or setup code and forgetting the Transport field; conditional wiring that leaves Transport unset on some code path; copying a snippet that used http.Transport then wrapping it later.

Related errors


AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01). Data as JSON: /api/errors/dbb8df15dfea4896. Report an issue: GitHub.