caddyserver/caddy · error

invalid file descriptor: %v

Error message

invalid file descriptor: %v

What it means

Unix-platform twin of the listen.go path: for network 'fd' or 'fdgram', the address must parse as an unsigned integer (base 0, int-sized). This error wraps the ParseUint failure — the address given for a file-descriptor listener is not a number.

Source

Thrown at listen_unix.go:109

}

// listenReusable creates a new listener for the given network and address, and adds it to listenerPool.
func listenReusable(ctx context.Context, lnKey string, network, address string, config net.ListenConfig) (any, error) {
	// even though SO_REUSEPORT lets us bind the socket multiple times,
	// we still put it in the listenerPool so we can count how many
	// configs are using this socket; necessary to ensure we can know
	// whether to enforce shutdown delays, for example (see #5393).
	var (
		ln         io.Closer
		err        error
		socketFile *os.File
	)

	fd := slices.Contains([]string{"fd", "fdgram"}, network)
	if fd {
		socketFd, err := strconv.ParseUint(address, 0, strconv.IntSize)
		if err != nil {
			return nil, fmt.Errorf("invalid file descriptor: %v", err)
		}

		func() {
			socketFilesMu.Lock()
			defer socketFilesMu.Unlock()

			socketFdWide := uintptr(socketFd)
			var ok bool

			socketFile, ok = socketFiles[socketFdWide]

			if !ok {
				socketFile = os.NewFile(socketFdWide, lnKey)
				if socketFile != nil {
					socketFiles[socketFdWide] = socketFile
				}
			}
		}()

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Provide the bare descriptor number as the address for the fd network.
  2. Keep unix paths under the 'unix' network, not 'fd'.
  3. Validate generated configs render the fd placeholder as an integer before deploy.

Example fix

// before
listen fd /run/caddy.sock
// after
listen fd 3
Defensive patterns

Strategy: validation

Validate before calling

func isFdNetwork(network string) bool { return network == "fd" || network == "fdgram" }

// before calling Listen:
// if isFdNetwork(na.Network) { ensure address is strconv-able }

Prevention

When it happens

Trigger: listen directives like 'listen fd /path/to/socket' (path instead of number), 'listen fd fd:3', empty address, or a number exceeding platform int size on Linux/macOS/BSD.

Common situations: Converting a unix-listen config to fd-based socket activation and leaving the path; templating that emits 'stdin' or a label where the fd number belongs.

Related errors


AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15). Data as JSON: /api/errors/38d759a4a9a3c40f. Report an issue: GitHub.