lima-vm/lima · info

UDPFileConn connection closed

Error message

UDPFileConn connection closed

What it means

UDPFileConn wraps a net.Conn and its Read first probes the connection by clearing the read deadline; if the underlying connection is already closed, the probe returns net.ErrClosed and Read converts it into the literal error "UDPFileConn connection closed" instead of attempting a read on a dead socket.

Source

Thrown at pkg/networks/usernet/udpfileconn.go:20

// SPDX-License-Identifier: Apache-2.0

package usernet

import (
	"errors"
	"net"
	"time"
)

type UDPFileConn struct {
	net.Conn
}

func (conn *UDPFileConn) Read(b []byte) (n int, err error) {
	// Check if the connection has been closed
	if err := conn.SetReadDeadline(time.Time{}); err != nil {
		if errors.Is(err, net.ErrClosed) {
			return 0, errors.New("UDPFileConn connection closed")
		}
	}
	return conn.Conn.Read(b)
}

View on GitHub (pinned to dd909d0973)

Solutions

  1. Treat this error as a normal shutdown signal: break the read loop and return without retrying.
  2. Synchronize: only call Read while the connection is open; signal readers via a done channel before calling Close().
  3. Use errors.Is-style comparison or string match on the returned error to detect closure and exit the loop cleanly.
  4. If you need the underlying net.ErrClosed, check conn.SetReadDeadline yourself before relying on Read.

Example fix

// before
for {
	n, err := udpConn.Read(buf)
	if err != nil {
		log.Fatal(err)
	}
}
// after
for {
	n, err := udpConn.Read(buf)
	if err != nil {
		if err.Error() == "UDPFileConn connection closed" || errors.Is(err, net.ErrClosed) {
			return nil // graceful shutdown
		}
		return err
	}
}
Defensive patterns

Strategy: try-catch

Type guard

function isConnClosed(err) {
  return err != null && (err.message === 'UDPFileConn connection closed' ||
    (typeof err.unwrap === 'function' && err === null) || /connection closed/i.test(err.message));
}

Try / catch

n, err := conn.Read(buf)
if err != nil {
	if err.Error() == "UDPFileConn connection closed" || errors.Is(err, net.ErrClosed) {
		return nil // expected during shutdown
	}
	return err
}

Prevention

When it happens

Trigger: A goroutine calls UDPFileConn.Read after the connection's Close() was called (e.g. the usernet daemon shut down or the peer handler closed the socket while a reader loop was still active).

Common situations: Hostagent or guestagent connection handler closing the UDP socket while a relay/packet-reading loop is concurrently blocked on Read; daemon shutdown racing with active connections.

Understand the failure class

Related errors


AI-assisted analysis of lima-vm/lima@dd909d0973 (2026-09-01). Data as JSON: /api/errors/5ab3d3e010b2f940. Report an issue: GitHub.