henrygd/beszel · error

failed to load %s: %w

Error message

failed to load %s: %w

What it means

The NVML collector's init fails when the NVIDIA Management Library shared object cannot be opened via purego/dlopen. This is thrown before any NVML calls are made, so it indicates a missing or unloadable libnvidia-ml library rather than an NVIDIA API error.

Source

Thrown at agent/gpu_nvml.go:82

	nvmlDeviceGetPciInfo          func(device nvmlDevice, pci *nvmlPciInfo) nvmlReturn
	nvmlErrorString               func(result nvmlReturn) string
)

type nvmlCollector struct {
	gm      *GPUManager
	lib     uintptr
	devices []nvmlDevice
	bdfs    []string
	isV2    bool
}

func (c *nvmlCollector) init() error {
	slog.Debug("NVML: Initializing")
	libPath := getNVMLPath()

	lib, err := openLibrary(libPath)
	if err != nil {
		return fmt.Errorf("failed to load %s: %w", libPath, err)
	}
	c.lib = lib

	purego.RegisterLibFunc(&nvmlInit, lib, "nvmlInit")
	purego.RegisterLibFunc(&nvmlShutdown, lib, "nvmlShutdown")
	purego.RegisterLibFunc(&nvmlDeviceGetCount, lib, "nvmlDeviceGetCount")
	purego.RegisterLibFunc(&nvmlDeviceGetHandleByIndex, lib, "nvmlDeviceGetHandleByIndex")
	purego.RegisterLibFunc(&nvmlDeviceGetName, lib, "nvmlDeviceGetName")
	// Try to get v2 memory info, fallback to v1 if not available
	if hasSymbol(lib, "nvmlDeviceGetMemoryInfo_v2") {
		c.isV2 = true
		purego.RegisterLibFunc(&nvmlDeviceGetMemoryInfo, lib, "nvmlDeviceGetMemoryInfo_v2")
	} else {
		purego.RegisterLibFunc(&nvmlDeviceGetMemoryInfo, lib, "nvmlDeviceGetMemoryInfo")
	}
	purego.RegisterLibFunc(&nvmlDeviceGetUtilizationRates, lib, "nvmlDeviceGetUtilizationRates")
	purego.RegisterLibFunc(&nvmlDeviceGetTemperature, lib, "nvmlDeviceGetTemperature")
	purego.RegisterLibFunc(&nvmlDeviceGetPowerUsage, lib, "nvmlDeviceGetPowerUsage")

View on GitHub (pinned to b38fb7dafa)

Solutions

  1. Install the NVIDIA driver so libnvidia-ml.so exists (nvidia-smi should work on the host).
  2. In containers, run with the NVIDIA container runtime / --gpus all so driver libraries are injected.
  3. Locate the lib and make it discoverable: export LD_LIBRARY_PATH=$(dirname $(ldconfig -p | grep libnvidia-ml | awk '{print $NF}')).
  4. Check the path returned by getNVMLPath and override if a different lib location is needed.
  5. On Alpine/musl, install glibc-compat or use a glibc-based image.

Example fix

// before (docker, no GPU runtime)
docker run beszel/agent
// after
docker run --gpus all beszel/agent
Defensive patterns

Strategy: validation

Validate before calling

// before deploying, confirm NVML is loadable:
ldconfig -p | grep libnvidia-ml || echo 'NVML missing'
nvidia-smi -L || echo 'driver unusable'

Try / catch

if err := c.init(); err != nil {
    if strings.Contains(err.Error(), "failed to load") {
        slog.Warn("NVML library unavailable; skipping NVML collector", "err", err)
        return nil
    }
    return err
}

Prevention

When it happens

Trigger: startNvmlCollector constructs an nvmlCollector and calls init(); getNVMLPath() returns a path and openLibrary(libPath) fails — library absent, wrong architecture, or unresolved symbols.

Common situations: NVIDIA driver not installed; headless/driverless setups; musl-based distros (Alpine) lacking glibc compatibility for the driver libs; container without NVIDIA runtime so no driver libs mounted; agent built for a different arch than the host.

Related errors


AI-assisted analysis of henrygd/beszel@b38fb7dafa (2026-08-31). Data as JSON: /api/errors/6fdb00c3fafc65a0. Report an issue: GitHub.