{"record":{"id":"dbb8df15dfea4896","repo":"jaegertracing/jaeger","slug":"no-http-roundtripper-provided","errorCode":null,"errorMessage":"no http.RoundTripper provided","messagePattern":"no http\\.RoundTripper provided","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/auth/transport.go","lineNumber":37,"sourceCode":"\tTokenFn func() string\n\n\t// FromCtx extracts token from context\n\tFromCtx func(context.Context) (string, bool)\n}\n\n// RoundTripper wraps another http.RoundTripper and injects\n// an authentication header with  token into requests.\ntype RoundTripper struct {\n\t// Transport is the underlying http.RoundTripper being wrapped. Required.\n\tTransport http.RoundTripper\n\tAuths     []Method\n}\n\n// RoundTrip injects the outbound Authorization header with the\n// token provided in the inbound request.\nfunc (tr RoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {\n\tif tr.Transport == nil {\n\t\treturn nil, errors.New(\"no http.RoundTripper provided\")\n\t}\n\n\treq := r.Clone(r.Context())\n\n\tfor _, auth := range tr.Auths {\n\t\ttoken := \"\"\n\n\t\t// Get token from context if available\n\t\tif auth.FromCtx != nil {\n\t\t\tif t, ok := auth.FromCtx(r.Context()); ok {\n\t\t\t\ttoken = t\n\t\t\t}\n\t\t}\n\n\t\t// Fall back to TokenFn if no token from context\n\t\tif token == \"\" && auth.TokenFn != nil {\n\t\t\ttoken = auth.TokenFn()\n\t\t}","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/jaegertracing/jaeger/blob/806f4447841ecdb60519f408b004a599d515f437/internal/auth/transport.go#L19-L55","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Set the Transport field explicitly, e.g. auth.RoundTripper{Transport: http.DefaultTransport, Auths: ...}","Or wrap an existing client: base := http.DefaultTransport; client.Transport = auth.RoundTripper{Transport: base, Auths: auths}","Add a constructor or init-time check that panics/errors on nil Transport before the client is used"],"exampleFix":"// before\nclient := &http.Client{\n  Transport: auth.RoundTripper{Auths: auths},\n}\n// after\nclient := &http.Client{\n  Transport: auth.RoundTripper{Transport: http.DefaultTransport, Auths: auths},\n}","handlingStrategy":"validation","validationCode":"rt := auth.RoundTripper{Transport: http.DefaultTransport, Auths: auths}\nif rt.Transport == nil {\n    return errors.New(\"auth.RoundTripper requires a non-nil Transport\")\n}","typeGuard":"func validRoundTripper(rt auth.RoundTripper) bool {\n    return rt.Transport != nil\n}","tryCatchPattern":"resp, err := client.Do(req)\nif err != nil {\n    if strings.Contains(err.Error(), \"no http.RoundTripper provided\") {\n        return fmt.Errorf(\"set RoundTripper.Transport: %w\", err)\n    }\n    return err\n}","preventionTips":["Always set Transport, e.g. http.DefaultTransport, when constructing auth.RoundTripper","Provide a constructor that fills a default Transport","Assert wiring in tests by issuing one real request through the client"],"tags":["go","http","authentication","roundtripper"],"backgroundTag":"nil-transport","analyzedSha":"806f4447841ecdb60519f408b004a599d515f437","analyzedAt":"2026-09-01T02:39:22.140Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}