gofiber/fiber · error · errNilProxyClientOverride

proxy: nil client override passed to Do/Forward

Error message

proxy: nil client override passed to Do/Forward

What it means

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.

Source

Thrown at middleware/proxy/proxy.go:144

				return err
			}
		}

		// Return nil to end proxying if no error
		return nil
	}
}

var defaultClient = &fasthttp.Client{
	NoDefaultUserAgentHeader: true,
	DisablePathNormalizing:   true,
	MaxConnsPerHost:          defaultMaxConnsPerHost,
}

var client atomic.Pointer[fasthttp.Client]

var (
	errNilProxyClientOverride = errors.New("proxy: nil client override passed to Do/Forward")
	errNilGlobalProxyClient   = errors.New("proxy: global client is nil, set a non-nil client with proxy.WithClient")
)

// guardedConfigureClient composes a client's optional pre-existing
// ConfigureClient hook with the dial-time SSRF guard. It is installed on a
// *fasthttp.Client as the bound method value (&guardedConfigureClient{…}).run,
// which fasthttp calls once per HostClient it creates — so the guard is
// present before the first dial to each host and covers both the Dial and
// DialTimeout code paths.
//
// The bound method's code pointer is stable across receivers (unlike a
// closure's), so ensureClientGuarded recognizes an already-guarded client by
// identity — no package-level map keyed by the client, which would pin the
// client and its connection pool for the process lifetime. The struct is
// referenced only from the client's own ConfigureClient field, so it is
// collected together with the client.
type guardedConfigureClient struct {
	// orig is the caller's ConfigureClient hook, or nil. It runs before the

View on GitHub (pinned to 9a4c7e57fe)

Solutions

  1. 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.
  2. Ensure any client variable is initialized before being passed.
  3. If conditionally using a custom client, branch: call Do with the client when set, and without when not.

Example fix

// before
var cli *fasthttp.Client
if useCustom { cli = customClient }
proxy.Do(c, target, cli) // cli may be nil
// after
if cli != nil {
  proxy.Do(c, target, cli)
} else {
  proxy.Do(c, target) // uses global default client
}
Defensive patterns

Strategy: validation

Validate before calling

// Never pass a nil client; branch instead
if customClient != nil {
    return proxy.Do(c, target, customClient)
}
return proxy.Do(c, target) // use global default

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of gofiber/fiber@9a4c7e57fe (2026-08-04). Data as JSON: /data/errors/b3e72598fce9de0d.json. Report an issue: GitHub.