Skip to content

fix(metrics): NewZerologMetrics returns nil on file open failure causing panic #595

@abhaygoudannavar

Description

@abhaygoudannavar

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions