gofiber/fiber · warning

failed to resolve TCP address: %w

Error message

failed to resolve TCP address: %w

What it means

The general failure path in resolveRemoteAddr: net.ResolveTCPAddr('tcp', remoteAddr) failed and the error was not the specific 'missing port in address' case that triggers the add-port retry. Covers malformed addresses, out-of-range ports, DNS lookup failures, and unknown address families. Like the add-port variant it is non-fatal for the request — remoteAddr becomes nil and the handler continues.

Source

Thrown at middleware/adaptor/adaptor.go:460

	resolved, err := net.ResolveTCPAddr("tcp", remoteAddr)
	if err == nil {
		return resolved, nil
	}

	var addrErr *net.AddrError
	if errors.As(err, &addrErr) && addrErr != nil && addrErr.Err == "missing port in address" {
		if len(remoteAddr) > 253 { // Max hostname length
			return nil, ErrRemoteAddrTooLong
		}
		remoteAddr = net.JoinHostPort(remoteAddr, "80")
		resolved, err2 := net.ResolveTCPAddr("tcp", remoteAddr)
		if err2 != nil {
			return nil, fmt.Errorf("failed to resolve TCP address after adding port: %w", err2)
		}
		return resolved, nil
	}
	return nil, fmt.Errorf("failed to resolve TCP address: %w", err)
}

func handlerFunc(app *fiber.App, h ...fiber.Handler) http.HandlerFunc {
	// App.Config returns the config by value, so read the body limit once at
	// construction instead of copying the whole 624-byte struct on every
	// request. Fiber only writes app.config in New. The error handler is
	// deliberately not cached: App.ErrorHandler resolves a mounted sub-app's
	// handler from the request path, and that lookup belongs per request.
	maxBodySize := int64(app.Config().BodyLimit)

	return func(w http.ResponseWriter, r *http.Request) {
		// New fasthttp Ctx from pool
		pctx := ctxPool.Get().(*pooledCtx) //nolint:forcetypeassert,errcheck // not needed
		fctx := &pctx.fctx
		fctx.Response.Reset()
		fctx.Request.Reset()
		defer ctxPool.Put(pctx)

View on GitHub (pinned to 9a4c7e57fe)

Solutions

  1. Normalize RemoteAddr to host:port form before it reaches the adapter; for IPv6 use bracketed form: net.JoinHostPort(host, port).
  2. Validate the address at your trust boundary (proxy/gateway) and reject/drop malformed X-Forwarded-For.
  3. If the value is a bare IP, append the well-known port yourself before delegating to the fiber adapter.
  4. Ensure DNS resolution works inside the container/host when RemoteAddr carries hostnames (configure /etc/resolv.conf or the resolver).

Example fix

// before: IPv6 without brackets -> 'cannot parse address'
r.RemoteAddr = "::1:80"

// after: bracketed IPv6 host:port via JoinHostPort
r.RemoteAddr = net.JoinHostPort("::1", "80") // -> "[::1]:80"
Defensive patterns

Strategy: validation

Validate before calling

// Validate RemoteAddr syntax before delegating to the fiber adapter.
func validRemoteAddr(addr string) bool {
    if addr == "" {
        return false
    }
    host, port, err := net.SplitHostPort(addr)
    if err != nil {
        return false
    }
    p, err := strconv.Atoi(port)
    return err == nil && p > 0 && p < 65536 && host != ""
}

Type guard

null

Try / catch

null

Prevention

When it happens

Trigger: Passing adaptor.FiberApp a request whose RemoteAddr is syntactically broken (e.g. '1.2.3.4:99999' — port out of range, 'not a host', or an IPv6 literal without brackets). Also fires when a hostname RemoteAddr cannot be resolved because DNS is unavailable in the current environment.

Common situations: IPv6 address without bracketed form ('::1:80' instead of '[::1]:80'); port > 65535 from a misconfigured proxy; ephemeral test containers with no DNS resolver; a TLS-terminating proxy that drops the port when forwarding.

Related errors


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