cilium/cilium · error

writing to file %v error: %w

Error message

writing to file %v error: %w

What it means

After successfully formatting the perf summary as JSON, exportSummary writes it to NetworkPerformance_benchmark_<timestamp>.json in the report directory (path required by perfdash). If os.WriteFile fails, the error is wrapped with this message naming the target path. The benchmark ran but its results were not persisted.

Source

Thrown at cilium-cli/connectivity/perf/common/metrics.go:195

				data[identifier+"th"] = res
			} else {
				maps.Copy(data[identifier+"th"].Data, res.Data)
			}
		}
	}
	return exportSummary(perfData{Version: "v1", DataItems: slices.Collect(maps.Values(data))}, reportDir)
}

func exportSummary(content perfData, reportDir string) error {
	// this filename needs to be in a specific format for perfdash
	fileName := strings.Join([]string{"NetworkPerformance_benchmark", time.Now().Format(time.RFC3339)}, "_")
	filePath := path.Join(reportDir, strings.Join([]string{fileName, "json"}, "."))
	contentStr, err := prettyPrintJSON(content)
	if err != nil {
		return fmt.Errorf("error formatting summary: %v error: %w", content, err)
	}
	if err := os.WriteFile(filePath, []byte(contentStr), 0600); err != nil {
		return fmt.Errorf("writing to file %v error: %w", filePath, err)
	}
	return nil
}

func prettyPrintJSON(data any) (string, error) {
	output := &bytes.Buffer{}
	if err := json.NewEncoder(output).Encode(data); err != nil {
		return "", fmt.Errorf("building encoder error: %w", err)
	}
	formatted := &bytes.Buffer{}
	if err := json.Indent(formatted, output.Bytes(), "", "  "); err != nil {
		return "", fmt.Errorf("indenting error: %w", err)
	}
	return formatted.String(), nil
}

View on GitHub (pinned to ac7b90affa)

Solutions

  1. Check the wrapped syscall error (ENOENT vs EACCES vs ENOSPC) for the exact cause
  2. Create the report directory before running: mkdir -p <reportDir>, or have exportSummary os.MkdirAll(reportDir, 0o755)
  3. Ensure the user running the test has write permission on reportDir and enough disk space
  4. Point --report-dir at a writable volume (e.g. CI artifact directory)

Example fix

// before
func exportSummary(content perfData, reportDir string) error {
	fileName := strings.Join([]string{"NetworkPerformance_benchmark", time.Now().Format(time.RFC3339)}, "_")
	filePath := path.Join(reportDir, strings.Join([]string{fileName, "json"}, "."))
// after
func exportSummary(content perfData, reportDir string) error {
	if err := os.MkdirAll(reportDir, 0o755); err != nil {
		return fmt.Errorf("creating report dir %s: %w", reportDir, err)
	}
	fileName := strings.Join([]string{"NetworkPerformance_benchmark", time.Now().Format(time.RFC3339)}, "_")
	filePath := path.Join(reportDir, strings.Join([]string{fileName, "json"}, "."))
Defensive patterns

Strategy: validation

Validate before calling

// before running perf tests
if err := os.MkdirAll(reportDir, 0o755); err != nil {
	log.Fatal(err)
}
if f, err := os.CreateTemp(reportDir, ".wtest"); err != nil {
	log.Fatalf("report dir %s not writable: %v", reportDir, err)
} else { f.Close(); os.Remove(f.Name()) }

Try / catch

if err := exportSummary(content, reportDir); err != nil {
	var pe *fs.PathError
	if errors.As(err, &pe) && (errors.Is(pe, os.ErrPermission) || errors.Is(pe, os.ErrNotExist)) {
		log.Printf("report dir issue (%s): %v — falling back to cwd", reportDir, err)
		return exportSummary(content, ".")
	}
	return err
}

Prevention

When it happens

Trigger: os.WriteFile(filePath, ..., 0600) fails — reportDir doesn't exist, is not writable by the test user, disk full, or path length/permission issues — when exporting perf summaries.

Common situations: Caller passed a --report-dir that was never created; read-only container filesystem; running tests as non-root in a directory owned by root; disk quota exceeded on CI runners.

Related errors


AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31). Data as JSON: /api/errors/7365e8c6cfdc24ed. Report an issue: GitHub.