kataras/iris · critical

err

Error message

err

What it means

monitor.New builds the monitoring middleware and attaches to the process identified by opts.PID using gopsutil's process.NewProcess. If no such process exists (or it cannot be inspected), New panics. The Monitor middleware must observe a real, live process at construction time.

Source

Thrown at middleware/monitor/monitor.go:76

	}

	if opts.RefreshInterval <= 0 {
		opts.RefreshInterval = 2 * opts.RefreshInterval
	}

	if opts.ViewRefreshInterval <= 0 {
		opts.ViewRefreshInterval = opts.RefreshInterval
	}

	viewRefreshIntervalBytes := []byte(fmt.Sprintf("%d", opts.ViewRefreshInterval.Milliseconds()))
	viewBody := bytes.Replace(defaultViewBody, viewRefreshIntervalTmplVar, viewRefreshIntervalBytes, 1)
	viewAnimationIntervalBytes := []byte(fmt.Sprintf("%d", opts.ViewAnimationInterval.Milliseconds()))
	viewBody = bytes.Replace(viewBody, viewAnimationIntervalTmplVar, viewAnimationIntervalBytes, 2)
	viewTitleBytes := []byte(opts.ViewTitle)
	viewBody = bytes.Replace(viewBody, viewTitleTmplVar, viewTitleBytes, 2)
	proc, err := process.NewProcess(opts.PID)
	if err != nil {
		panic(err)
	}

	sh := startNewStatsHolder(proc, opts.RefreshInterval)
	m := &Monitor{
		opts:     opts,
		Holder:   sh,
		viewBody: viewBody,
	}

	return m
}

// Stop terminates the retrieve stats loop for
// the process and the operating system statistics.
// No other monitor instance should be initialized after the first Stop call.
func (m *Monitor) Stop() {
	m.Holder.Stop()
}

View on GitHub (pinned to 7bedaf55a0)

Solutions

  1. Keep the default PID (zero/current process) or set Configuration.PID to os.Getpid().
  2. Ensure /proc is accessible: run the container with sufficient privileges or mount /proc properly.
  3. Verify the target process exists before constructing: check process.PidExists from gopsutil or guard with a recover.

Example fix

// before
cfg := monitor.DefaultConfiguration
cfg.PID = pidFromEnv // empty -> invalid
m := monitor.New(cfg)
// after
cfg := monitor.DefaultConfiguration
cfg.PID = os.Getpid()
m := monitor.New(cfg)
Defensive patterns

Strategy: fallback

Validate before calling

if cfg.PID != 0 {
    exists, err := process.PidExists(int32(cfg.PID))
    if err != nil || !exists {
        return fmt.Errorf("monitor pid %d unavailable: %w", cfg.PID, err)
    }
}

Try / catch

defer func() {
    if r := recover(); r != nil {
        log.Printf("monitor disabled: %v", r)
    }
}()
m := monitor.New(cfg)

Prevention

When it happens

Trigger: Calling monitor.New(monitor.DefaultConfiguration) inside a container or restricted environment where /proc access to the given PID fails, or configuring a PID that is not the current process and does not exist. The default PID is the current process (os.Getpid()), so the panic usually means /proc is unavailable or the process exited.

Common situations: Running inside minimal Docker/alpine images or Kubernetes sidecars without /proc mounted readably; hardened containers (hidepid); passing a parent PID from an env var that is empty; using a PID from another PID namespace.

Related errors


AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30). Data as JSON: /api/errors/8b95807d95007307. Report an issue: GitHub.