{"id":"b3e72598fce9de0d","repo":"gofiber/fiber","slug":"proxy-nil-client-override-passed-to-do-forward","errorCode":null,"errorMessage":"proxy: nil client override passed to Do/Forward","messagePattern":"proxy: nil client override passed to Do/Forward","errorType":"http","errorClass":"errNilProxyClientOverride","httpStatus":null,"severity":"error","filePath":"middleware/proxy/proxy.go","lineNumber":144,"sourceCode":"\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\n\t\t// Return nil to end proxying if no error\n\t\treturn nil\n\t}\n}\n\nvar defaultClient = &fasthttp.Client{\n\tNoDefaultUserAgentHeader: true,\n\tDisablePathNormalizing:   true,\n\tMaxConnsPerHost:          defaultMaxConnsPerHost,\n}\n\nvar client atomic.Pointer[fasthttp.Client]\n\nvar (\n\terrNilProxyClientOverride = errors.New(\"proxy: nil client override passed to Do/Forward\")\n\terrNilGlobalProxyClient   = errors.New(\"proxy: global client is nil, set a non-nil client with proxy.WithClient\")\n)\n\n// guardedConfigureClient composes a client's optional pre-existing\n// ConfigureClient hook with the dial-time SSRF guard. It is installed on a\n// *fasthttp.Client as the bound method value (&guardedConfigureClient{…}).run,\n// which fasthttp calls once per HostClient it creates — so the guard is\n// present before the first dial to each host and covers both the Dial and\n// DialTimeout code paths.\n//\n// The bound method's code pointer is stable across receivers (unlike a\n// closure's), so ensureClientGuarded recognizes an already-guarded client by\n// identity — no package-level map keyed by the client, which would pin the\n// client and its connection pool for the process lifetime. The struct is\n// referenced only from the client's own ConfigureClient field, so it is\n// collected together with the client.\ntype guardedConfigureClient struct {\n\t// orig is the caller's ConfigureClient hook, or nil. It runs before the","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/gofiber/fiber/blob/9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c/middleware/proxy/proxy.go#L126-L162","documentation":"Returned by proxy.selectClient (proxy.go:144, 546) when Do/Forward/DoRedirects is called with a variadic client override argument whose first element is nil. selectClient resolves which *fasthttp.Client to use: if clients are passed, it uses clients[0], but if that is nil it returns this error rather than panicking on a nil dereference. This is an unexported error (lowercase) returned to the caller of Do/Forward.","triggerScenarios":"Calling proxy.Do(c, url, nil) or proxy.Forward(addr, nilClient) — explicitly passing a nil *fasthttp.Client as the optional override. This is a programmer error in the calling code, not a runtime/config issue.","commonSituations":"Conditionally building a client and passing it even when the condition didn't set it (var cli *fasthttp.Client; ...; proxy.Do(c, url, cli)); refactoring that leaves a nil where a client was expected; testing code that passes nil as a placeholder.","solutions":["Do not pass a nil client — if you have no custom client, call Do/Forward without the clients argument so the global default client is used.","Ensure any client variable is initialized before being passed.","If conditionally using a custom client, branch: call Do with the client when set, and without when not."],"exampleFix":"// before\nvar cli *fasthttp.Client\nif useCustom { cli = customClient }\nproxy.Do(c, target, cli) // cli may be nil\n// after\nif cli != nil {\n  proxy.Do(c, target, cli)\n} else {\n  proxy.Do(c, target) // uses global default client\n}","handlingStrategy":"validation","validationCode":"// Never pass a nil client; branch instead\nif customClient != nil {\n    return proxy.Do(c, target, customClient)\n}\nreturn proxy.Do(c, target) // use global default","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only pass the variadic client argument when you have a non-nil client.","Initialize client variables before use.","Code-review proxy call sites for conditional client passing."],"tags":["proxy","configuration","nil-check","client"],"analyzedSha":"9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c","analyzedAt":"2026-08-04T21:44:03.395Z","schemaVersion":2}