{"record":{"id":"6b3414b9abfd9ca4","repo":"grafana/k6","slug":"could-not-open-s-w","errorCode":null,"errorMessage":"could not open '%s': %w","messagePattern":"could not open '(.+?)': %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cmd/run.go","lineNumber":607,"sourceCode":"}\n\nfunc handleSummaryResult(fs fsext.Fs, stdOut, stdErr io.Writer, result map[string]io.Reader) error {\n\tvar errs []error\n\n\tgetWriter := func(path string) (io.Writer, error) {\n\t\tswitch path {\n\t\tcase \"stdout\":\n\t\t\treturn stdOut, nil\n\t\tcase \"stderr\":\n\t\t\treturn stdErr, nil\n\t\tdefault:\n\t\t\treturn fs.OpenFile(path, syscall.O_WRONLY|syscall.O_CREAT|syscall.O_TRUNC, 0o666)\n\t\t}\n\t}\n\n\tfor path, value := range result {\n\t\tif writer, err := getWriter(path); err != nil {\n\t\t\terrs = append(errs, fmt.Errorf(\"could not open '%s': %w\", path, err))\n\t\t} else if n, err := io.Copy(writer, value); err != nil {\n\t\t\terrs = append(errs, fmt.Errorf(\"error saving summary to '%s' after %d bytes: %w\", path, n, err))\n\t\t}\n\t}\n\n\treturn consolidateErrorMessage(errs, \"Could not save some summary information:\")\n}\n","sourceCodeStart":589,"sourceCodeEnd":615,"githubUrl":"https://github.com/grafana/k6/blob/3fcf5388d78cb382f0c0d42ec556a06bfd1b8dee/internal/cmd/run.go#L589-L615","documentation":"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.","triggerScenarios":"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.","commonSituations":"Summary templates from blog posts/docs writing into subdirectories that CI never creates; containers with read-only mounts; first run in a fresh checkout.","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"],"exampleFix":"# before\n# script: return { './reports/summary.json': JSON.stringify(data) } — reports/ missing\n\n# after\nmkdir -p reports && k6 run script.js\n# or write next to cwd: return { 'summary.json': JSON.stringify(data) }","handlingStrategy":"validation","validationCode":"# ensure every summary destination directory exists and is writable\nfor d in reports out/summary; do\n  mkdir -p \"$d\" || exit 1\n  [ -w \"$d\" ] || { echo \"$d is not writable\" >&2; exit 1; }\ndone\nk6 run script.js","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["k6","summary","handle-summary","file-io","permissions"],"backgroundTag":"cannot-open-file","analyzedSha":"3fcf5388d78cb382f0c0d42ec556a06bfd1b8dee","analyzedAt":"2026-08-18T03:05:52.393Z","contentChangedAt":"2026-08-18T03:05:52.393Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}