netbirdio/netbird · error

converting fd to file failed

Error message

converting fd to file failed

What it means

Returned by rawsocket.prepareSenderRawSocket when os.NewFile(uintptr(fd), ...) returns nil. os.NewFile in modern Go never returns nil for a valid non-negative fd; it returns nil only if handed something like an invalid handle. Because fd comes straight from a successful syscall.Socket, this branch is a defensive invariant check that is effectively unreachable.

Source

Thrown at client/iface/wgproxy/rawsocket/rawsocket.go:78

		return nil, fmt.Errorf("binding to lo interface failed: %w", err)
	}

	// Set the fwmark on the socket.
	err = nbnet.SetSocketOpt(fd)
	if err != nil {
		if closeErr := syscall.Close(fd); closeErr != nil {
			log.Warnf("failed to close raw socket fd: %v", closeErr)
		}
		return nil, fmt.Errorf("setting fwmark failed: %w", err)
	}

	// Convert the file descriptor to a PacketConn.
	file := os.NewFile(uintptr(fd), fmt.Sprintf("fd %d", fd))
	if file == nil {
		if closeErr := syscall.Close(fd); closeErr != nil {
			log.Warnf("failed to close raw socket fd: %v", closeErr)
		}
		return nil, fmt.Errorf("converting fd to file failed")
	}
	packetConn, err := net.FilePacketConn(file)
	if err != nil {
		if closeErr := file.Close(); closeErr != nil {
			log.Warnf("failed to close file: %v", closeErr)
		}
		return nil, fmt.Errorf("converting file to packet conn failed: %w", err)
	}

	// Close the original file to release the FD (net.FilePacketConn duplicates it)
	if closeErr := file.Close(); closeErr != nil {
		log.Warnf("failed to close file after creating packet conn: %v", closeErr)
	}

	return packetConn, nil
}

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Treat as an internal invariant failure: report the fd value and Go version to NetBird
  2. Audit any local fork for code that closes or reuses the fd between syscall.Socket and os.NewFile
  3. No configuration change affects this path
Defensive patterns

Strategy: try-catch

Try / catch

// treat as an invariant breach: nothing at call-site level can prevent it
if _, err := rawsocket.PrepareSenderRawSocketIPv4(); err != nil && strings.Contains(err.Error(), "converting fd to file") {
    panic(fmt.Sprintf("raw socket fd invariant broken: %v", err)) // surfaces the bug instead of half-starting
}

Prevention

When it happens

Trigger: Only reachable if syscall.Socket returned a nonsensical fd value (negative or otherwise invalid) without error, or Go runtime internals changed under the code. No realistic API call produces it.

Common situations: Practically never seen; if it ever fires, suspect memory corruption, an aggressively patched runtime, or a fork of the repo that changed the fd plumbing above this call.

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/7d03b3ec45e3152f. Report an issue: GitHub.