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
- Re-run the benchmark (k9s bench on the pod) to regenerate the file
- Verify the benchDir setting in k9s config points to the directory that actually holds the files
- Check permissions on the file and directory for the user running k9s
- 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
- os.Stat bench files before rendering rows
- Do not clear the benchDir cache while the bench view is open
- Keep benchDir consistent across k9s configs on the same machine
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
- invalid file name %s
- no dir in context
- failed benchmark
- you must select a reachable service
- expecting screendumper, but got %T
AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15).
Data as JSON: /api/errors/e49f0fa9b3dde429.
Report an issue: GitHub.