derailed/k9s · error

unable to load bench file %s

Error message

unable to load bench file %s

What it means

Benchmark.Render reads the benchmark result file at BenchInfo.Path via os.ReadFile; any read failure (file deleted, moved, permission denied) is replaced by this error. Note the code drops the underlying cause by formatting the path with %s instead of wrapping err with %w, so the real reason (ENOENT vs EACCES) is invisible.

Source

Thrown at internal/render/benchmark.go:72

		model1.HeaderColumn{Name: "REQ/S", Attrs: model1.Attrs{Align: tview.AlignRight}},
		model1.HeaderColumn{Name: "2XX", Attrs: model1.Attrs{Align: tview.AlignRight}},
		model1.HeaderColumn{Name: "4XX/5XX", Attrs: model1.Attrs{Align: tview.AlignRight}},
		model1.HeaderColumn{Name: "REPORT"},
		model1.HeaderColumn{Name: "VALID", Attrs: model1.Attrs{Wide: true}},
		model1.HeaderColumn{Name: "AGE", Attrs: model1.Attrs{Time: true}},
	}
}

// Render renders a K8s resource to screen.
func (b Benchmark) Render(o any, ns string, r *model1.Row) error {
	bench, ok := o.(BenchInfo)
	if !ok {
		return fmt.Errorf("no benchmarks available %T", o)
	}

	data, err := b.readFile(bench.Path)
	if err != nil {
		return fmt.Errorf("unable to load bench file %s", bench.Path)
	}

	r.ID = bench.Path
	r.Fields = make(model1.Fields, len(b.Header(ns)))
	if err := b.initRow(r.Fields, bench.File); err != nil {
		return err
	}
	b.augmentRow(r.Fields, data)
	r.Fields[8] = AsStatus(b.diagnose(ns, r.Fields))

	return nil
}

// Happy returns true if resource is happy, false otherwise.
func (Benchmark) diagnose(ns string, ff model1.Fields) error {
	statusCol := 3
	if !client.IsAllNamespaces(ns) {
		statusCol--

View on GitHub (pinned to 2d3ccc6ba2)

Solutions

  1. Re-run the benchmark (k9s bench on the pod) to regenerate the file
  2. Verify the benchDir setting in k9s config points to the directory that actually holds the files
  3. Check permissions on the file and directory for the user running k9s
  4. Refresh/reopen the benchmark view to re-list the directory instead of using stale paths

Example fix

// before: stale path rendered after cache wipe
// after: re-run the bench
// k9s: select pod -> bench -> choose container/command, file is recreated under benchDir
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := os.Stat(bench.Path); err != nil {
	// skip row / re-run bench instead of rendering
	return nil
}

Type guard

func asBenchInfo(o any) (BenchInfo, bool) {
	b, ok := o.(BenchInfo)
	return b, ok
}

Try / catch

Wrap Benchmark.Render per-row: on error containing 'unable to load bench file', drop the row from the view and log the path; do not fail the whole table render.

Prevention

When it happens

Trigger: The bench directory listing happened, then the file was removed before Render read it; benchDir config points elsewhere; file permissions changed; empty Path.

Common situations: Clearing the k9s cache (~/.cache/k9s or the configured benchDir) while the benchmark view is open; two k9s instances with different benchDir configs; backup/restore that skipped bench files.

Related errors


AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15). Data as JSON: /api/errors/e49f0fa9b3dde429. Report an issue: GitHub.