gofiber/fiber · error · ErrorInvalidURI

%w: %w

Error message

%w: %w

What it means

When following a redirect, composeRedirectURL re-parses the resolved URI with fasthttp and, if Parse rejects it, returns this dual-wrapped error: fasthttp.ErrorInvalidURI wrapping the concrete parse cause. It signals that the redirect's Location header (combined with the base URL) does not form a valid URI — e.g. a bad port, illegal host bytes, or scheme/host inconsistency that fasthttp's UpdateBytes silently tolerated but Parse caught.

Source

Thrown at client/transport.go:491

}

// composeRedirectURL resolves a redirect target relative to the current request
// URL while rejecting suspicious payloads (e.g. control characters) and
// restricting schemes to HTTP/S so caller-provided Location headers cannot
// trigger arbitrary transports. Redirects from HTTPS to plaintext HTTP are
// rejected to prevent credentials from leaking after a TLS handshake.
//
// It returns the resolved URL along with its host, which the caller compares
// against the previous hop to decide whether origin-scoped credentials still
// apply.
// parsesAsURI reports whether fasthttp reads full as a URI at all, returning the
// reason it does not. Only Parse surfaces that; Update and UpdateBytes discard it.
func parsesAsURI(full []byte) error {
	check := fasthttp.AcquireURI()
	defer fasthttp.ReleaseURI(check)

	if err := check.Parse(nil, full); err != nil {
		return fmt.Errorf("%w: %w", fasthttp.ErrorInvalidURI, err)
	}
	return nil
}

func composeRedirectURL(base string, location []byte, disablePathNormalizing bool) (redirectURL, host string, err error) { //nolint:nonamedreturns // names document the two string results
	for _, b := range location {
		if b < 0x20 || b == 0x7f {
			return "", "", fasthttp.ErrorInvalidURI
		}
	}

	uri := fasthttp.AcquireURI()
	defer fasthttp.ReleaseURI(uri)

	uri.Update(base)
	wasHTTPS := utils.EqualFold(uri.Scheme(), httpsScheme)
	uri.UpdateBytes(location)
	uri.DisablePathNormalizing = disablePathNormalizing

View on GitHub (pinned to a105acad6c)

Solutions

  1. Disable redirect following (maxRedirects = 0) if you do not trust upstream Location headers, and resolve redirects yourself.
  2. Validate the Location header with net/url.Parse before following if you implement a custom redirect policy.
  3. Log the wrapped cause — it specifies the exact parse failure (port, host, scheme).

Example fix

// before
c.SetRedirectPolicy(client.RedirectPolicy{MaxRedirects: 10})

// after (opt out and handle manually)
c.SetRedirectPolicy(client.RedirectPolicy{MaxRedirects: 0})
loc := resp.RawResponse.Header.Peek("Location")
u, err := url.Parse(string(loc))
if err != nil { return fmt.Errorf("bad redirect: %w", err) }
Defensive patterns

Strategy: validation

Validate before calling

loc := resp.RawResponse.Header.Peek("Location")
if _, err := url.Parse(string(loc)); err != nil {
    return fmt.Errorf("upstream returned bad redirect: %w", err)
}

Try / catch

if maxRedirects == 0 || err != nil && errors.Is(err, fasthttp.ErrorInvalidURI) {
    // do not follow; surface to caller
}

Prevention

When it happens

Trigger: A server returns a Location header with an invalid port (http://host:abc/x), malformed IPv6 literal, control bytes that survived the earlier filter, or a scheme that fasthttp rejects. The earlier 0x20/0x7f filter and scheme checks (http/https only, HTTPS→HTTP downgrade) run first; reaching this line means a subtler URI defect.

Common situations: Misconfigured upstream returning a broken Location; a reverse proxy rewriting Location incorrectly; an attacker-controlled redirect crafted to stress URI parsers; fasthttp version differences in strictness.

Related errors


AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11). Data as JSON: /api/errors/e227d5bb5a9054a2. Report an issue: GitHub.