grafana/k6 · error
could not open
Error message
could not open '%s': %w
What it means
A handleSummary() (or --summary-export style) result can write to files: for any key other than 'stdout'/'stderr', k6 opens the path with O_WRONLY|O_CREAT|O_TRUNC (mode 0666). If the open fails — missing parent directory, no permission, read-only filesystem, path is a directory — the failure is wrapped as 'could not open <path>'. Multiple failures are consolidated under 'Could not save some summary information:'. Note the file is truncated if it already exists.
Solutions
- Create the target directory before the run: mkdir -p reports
- Use an absolute, writable path, or the special 'stdout'/'stderr' keys
- Check directory permissions for the user running k6 — it needs write+create on the directory, and remember an existing file gets truncated
Example fix
# before
# script: return { './reports/summary.json': JSON.stringify(data) } — reports/ missing
# after
mkdir -p reports && k6 run script.js
# or write next to cwd: return { 'summary.json': JSON.stringify(data) } Defensive patterns
Strategy: validation
Validate before calling
# ensure every summary destination directory exists and is writable
for d in reports out/summary; do
mkdir -p "$d" || exit 1
[ -w "$d" ] || { echo "$d is not writable" >&2; exit 1; }
done
k6 run script.js Prevention
- Create summary directories in the CI step before running k6 (mkdir -p)
- Prefer writing summaries to stdout and redirecting when the filesystem is uncertain
- Remember existing summary files are truncated (O_TRUNC) — back up previous reports before reruns
When it happens
Trigger: handleSummary returning { 'reports/summary.json': ... } when reports/ does not exist; writing into a directory the k6 process cannot modify; read-only container filesystem; key path pointing at a directory.
Common situations: Summary templates from blog posts/docs writing into subdirectories that CI never creates; containers with read-only mounts; first run in a fresh checkout.
Related errors
AI-assisted analysis of grafana/k6@3fcf5388d7 (2026-08-18).
Data as JSON: /api/errors/6b3414b9abfd9ca4.
Report an issue: GitHub.
Appendix: source
Thrown at internal/cmd/run.go:607
}
func handleSummaryResult(fs fsext.Fs, stdOut, stdErr io.Writer, result map[string]io.Reader) error {
var errs []error
getWriter := func(path string) (io.Writer, error) {
switch path {
case "stdout":
return stdOut, nil
case "stderr":
return stdErr, nil
default:
return fs.OpenFile(path, syscall.O_WRONLY|syscall.O_CREAT|syscall.O_TRUNC, 0o666)
}
}
for path, value := range result {
if writer, err := getWriter(path); err != nil {
errs = append(errs, fmt.Errorf("could not open '%s': %w", path, err))
} else if n, err := io.Copy(writer, value); err != nil {
errs = append(errs, fmt.Errorf("error saving summary to '%s' after %d bytes: %w", path, n, err))
}
}
return consolidateErrorMessage(errs, "Could not save some summary information:")
}
View on GitHub (pinned to 3fcf5388d7)