gofiber/fiber · critical · ErrUpstreamSchemeNotAllowed
proxy: upstream scheme is not allowed
Error message
proxy: upstream scheme is not allowed
What it means
Returned by proxy.parseUpstreamScheme (security.go:50, 331) when the upstream URL's scheme is not in the configured AllowedSchemes allowlist (default: 'http' and 'https'). The proxy enforces a scheme allowlist to prevent SSRF via exotic schemes (gopher://, file://, etc.). It fires during validateUpstream, which runs at request time for Do/Forward and at construction time (panic) for DomainForward/BalancerForward.
Source
Thrown at middleware/proxy/security.go:50
// defaultAllowedSchemes is the internal, read-only allowlist used as the
// fallback inside schemeAllowed when a policy carries no AllowedSchemes.
// It is never handed out by reference: DefaultSecurityPolicy() and
// normalizePolicy() copy it before it can reach the exported
// SecurityPolicy.AllowedSchemes field, so nothing outside this file can
// mutate the backing array.
var defaultAllowedSchemes = []string{schemeHTTP, schemeHTTPS}
// httpsSchemeBytes is the byte form of "https" used by redirect
// downgrade checks. Stored once so the resolveRedirect hot path doesn't
// allocate []byte("https") on every hop.
var httpsSchemeBytes = []byte(schemeHTTPS)
// Sentinel errors returned when an upstream target violates the configured
// proxy security policy.
var (
// ErrUpstreamSchemeNotAllowed is returned when the proxied URL uses a
// scheme outside the configured allowlist (default: http, https).
ErrUpstreamSchemeNotAllowed = errors.New("proxy: upstream scheme is not allowed")
// ErrUpstreamHostInvalid is returned when the proxied URL is missing a
// host or cannot be parsed.
ErrUpstreamHostInvalid = errors.New("proxy: upstream host is empty or invalid")
// ErrUpstreamHostBlocked is returned when the proxied URL resolves to
// an address inside a blocked range (loopback, RFC 1918 private,
// link-local, multicast, unspecified, or CGNAT) and AllowPrivateIPs
// is false.
ErrUpstreamHostBlocked = errors.New("proxy: upstream host resolves to a blocked address")
// ErrRedirectDowngrade is returned when DoRedirects encounters a
// redirect from an HTTPS upstream to a plaintext HTTP target and
// AllowHTTPSDowngrade is false.
ErrRedirectDowngrade = errors.New("proxy: HTTPS to HTTP redirect blocked")
)
// SecurityPolicy controls runtime security restrictions applied to theView on GitHub (pinned to 9a4c7e57fe)
Solutions
- Use only 'http://' or 'https://' upstream URLs unless you have explicitly added other schemes to SecurityPolicy.AllowedSchemes.
- If you legitimately need another scheme, add it to SecurityPolicy.AllowedSchemes in your proxy config (review the SSRF implications first).
- For DomainForward/BalancerForward, fix the scheme before deployment since it panics at startup.
Example fix
// before — startup panic
proxy.BalancerForward([]string{"gopher://internal:7070"})
// after
proxy.BalancerForward([]string{"http://internal:7070"})
// or extend the allowlist deliberately
proxy.SetSecurityPolicy(proxy.SecurityPolicy{AllowedSchemes: []string{"http", "https", "ws"}}) Defensive patterns
Strategy: validation
Validate before calling
// Validate the upstream scheme before configuring
u, err := url.Parse(upstream)
if err != nil || (u.Scheme != "http" && u.Scheme != "https") {
log.Fatalf("upstream %q must use http or https", upstream)
} Prevention
- Restrict upstream URLs to http/https unless you deliberately extend AllowedSchemes.
- For DomainForward/BalancerForward, test startup locally to catch scheme panics before deploy.
- Review SecurityPolicy.AllowedSchemes changes with SSRF risk in mind.
When it happens
Trigger: Configuring an upstream with a scheme like 'gopher://', 'ftp://', 'file://', or 'ws://' when AllowedSchemes only permits http/https. For DomainForward/BalancerForward this panics at startup (security_test.go:843); for Do/Forward it returns the error per-request. An empty scheme also fails (schemeAllowed returns false for "").
Common situations: Typing 'ftp://' or omitting the scheme (which parseUpstream defaults to http://, so this is fine, but a truly empty scheme fails); intentionally proxying to a non-http service; misconfigured SecurityPolicy.AllowedSchemes that drops http/https; copied upstream URLs that include unexpected schemes.
Related errors
- ErrUpstreamSchemeNotAllowed
- ErrUpstreamHostBlocked
- proxy: upstream host is empty or invalid
- proxy: upstream host resolves to a blocked address
- csrf: referer does not match host or trusted origins
AI-assisted analysis of gofiber/fiber@9a4c7e57fe (2026-08-04).
Data as JSON: /data/errors/f4b72a331b69c84d.json.
Report an issue: GitHub.