slackhq/nebula · error

Read failed: %w

Error message

Read failed: %w

What it means

Catch-all wrapping error at the end of NativeTun.Read's switch: ReceivePacket returned an error other than the handled cases (ERROR_NO_MORE_ITEMS, ERROR_HANDLE_EOF, ERROR_INVALID_DATA). An unexpected Wintun driver error on read; preserved with %w. Handled cases exit earlier, so reaching this line is abnormal.

Source

Thrown at wintun/tun.go:148

		case nil:
			packetSize := len(packet)
			copy(buff[offset:], packet)
			tun.session.ReleaseReceivePacket(packet)
			tun.rate.update(uint64(packetSize))
			return packetSize, nil
		case windows.ERROR_NO_MORE_ITEMS:
			if !shouldSpin || uint64(nanotime()-start) >= spinloopDuration {
				windows.WaitForSingleObject(tun.readWait, windows.INFINITE)
				goto retry
			}
			procyield(1)
			continue
		case windows.ERROR_HANDLE_EOF:
			return 0, os.ErrClosed
		case windows.ERROR_INVALID_DATA:
			return 0, errors.New("Send ring corrupt")
		}
		return 0, fmt.Errorf("Read failed: %w", err)
	}
}

func (tun *NativeTun) Flush() error {
	return nil
}

func (tun *NativeTun) Write(buff []byte, offset int) (int, error) {
	tun.running.Add(1)
	defer tun.running.Done()
	if atomic.LoadInt32(&tun.close) == 1 {
		return 0, os.ErrClosed
	}

	packetSize := len(buff) - offset
	tun.rate.update(uint64(packetSize))

	packet, err := tun.session.AllocateSendPacket(packetSize)

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Retry the read — transient driver errors often clear
  2. Recreate the TUN device if the error persists
  3. Report the wrapped Windows error code to diagnose the driver state
Defensive patterns

Strategy: retry

When it happens

Trigger: Thrown at wintun/tun.go:148 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/c5637baa769f8462. Report an issue: GitHub.