Description
When timestamps are enabled in the urunc configuration (/etc/urunc/config.toml) but the target file path is invalid or the parent directory does not exist, NewZerologMetrics() in internal/metrics/metrics.go returns nil instead of a safe fallback writer.The caller in cmd/urunc/main.go (line 142) assigns the return value directly to the global metrics variable without performing a nil check:
metrics = m.NewZerologMetrics(cfg.Timestamps.Enabled, cfg.Timestamps.Destination, "")
Since metrics is used throughout the codebase via metrics.Capture() calls (19+ occurrences across create.go, start.go, and unikontainers.go), any subsequent invocation results in a nil pointer dereference, crashing urunc silently.
This is especially impactful for new users who enable timestamps in their config but haven't yet created the log directory (e.g., /var/log/urunc/).
Root Cause
In internal/metrics/metrics.go, the NewZerologMetrics function:
file, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
return nil // ← this causes the panic
}
When enabled=false, the function correctly returns &mockWriter{} (a safe no-op). But when enabled=true and the file open fails, it returns nil instead of the same safe fallback.
Proposed Fix
Return a &mockWriter{} (no-op writer) instead of nil on file open failure, and log a warning to inform the user that metrics have been disabled due to the file error:
if err != nil {
logrus.Warnf("Failed to open metrics file %s: %v. Metrics will be disabled.", target, err)
return &mockWriter{}
}
This ensures urunc continues to function normally with metrics gracefully degraded, rather than crashing.
System info
- Urunc version: main (commit HEAD)
- Arch: x86_64 (amd64)
- VMM: Any (bug is in metrics initialization, not VMM-specific)
- Unikernel: Any (bug is in metrics initialization, not unikernel-specific)
Steps to reproduce
- Enable timestamps in /etc/urunc/config.toml:
[timestamps]
enabled = true
destination = "/var/log/urunc/timestamps.log"
- Make sure the destination directory does not exist:
sudo rm -rf /var/log/urunc/
- Run any urunc command (e.g., create a container):
sudo nerdctl run --rm --runtime io.containerd.urunc.v2 \
harbor.nbfc.io/nubificus/urunc/nginx-qemu-unikraft-initrd:latest
- Expected behavior: urunc starts normally, logs a warning that metrics file could not be opened, and disables metrics gracefully.
- Actual behavior: urunc crashes with a nil pointer dereference panic at the first metrics.Capture() call.
Description
When timestamps are enabled in the urunc configuration (/etc/urunc/config.toml) but the target file path is invalid or the parent directory does not exist, NewZerologMetrics() in internal/metrics/metrics.go returns nil instead of a safe fallback writer.The caller in cmd/urunc/main.go (line 142) assigns the return value directly to the global metrics variable without performing a nil check:
Since metrics is used throughout the codebase via metrics.Capture() calls (19+ occurrences across create.go, start.go, and unikontainers.go), any subsequent invocation results in a nil pointer dereference, crashing urunc silently.
This is especially impactful for new users who enable timestamps in their config but haven't yet created the log directory (e.g., /var/log/urunc/).
Root Cause
In internal/metrics/metrics.go, the NewZerologMetrics function:
When enabled=false, the function correctly returns &mockWriter{} (a safe no-op). But when enabled=true and the file open fails, it returns nil instead of the same safe fallback.
Proposed Fix
Return a &mockWriter{} (no-op writer) instead of nil on file open failure, and log a warning to inform the user that metrics have been disabled due to the file error:
This ensures urunc continues to function normally with metrics gracefully degraded, rather than crashing.
System info
Steps to reproduce