cloudflare/cloudflared · error

error opening file %s: %w

Error message

error opening file %s: %w

What it means

Wrapped os.Open failure inside the per-file loop of diagnostic CopyFilesFromDirectory: one of the rolling log files in the directory could not be opened (deleted mid-iteration or permission denied), aborting the copy of the log bundle.

Source

Thrown at diagnostic/log_collector_utils.go:91

	// when iterating the path files they are already in
	// chronological order
	files, err := os.ReadDir(path)
	if err != nil {
		return "", fmt.Errorf("error reading directory %s: %w", path, err)
	}

	// nolint: gosec
	outputHandle, err := os.Create(filepath.Join(os.TempDir(), logFilename))
	if err != nil {
		return "", fmt.Errorf("creating temporary log file %s: %w", logFilename, err)
	}
	defer func() { _ = outputHandle.Close() }()

	for _, file := range files {
		// nolint: gosec
		logHandle, err := os.Open(filepath.Join(path, file.Name()))
		if err != nil {
			return "", fmt.Errorf("error opening file %s: %w", file.Name(), err)
		}
		_, err = io.Copy(outputHandle, logHandle)
		_ = logHandle.Close()
		if err != nil {
			return "", fmt.Errorf("error copying file %s: %w", file.Name(), err)
		}
	}

	// nolint: gosec
	logHandle, err := os.Open(filepath.Join(path, defaultLogFilename))
	if err != nil {
		return "", fmt.Errorf("error opening file %s:%w", defaultLogFilename, err)
	}
	defer func() { _ = logHandle.Close() }()

	_, err = io.Copy(outputHandle, logHandle)
	if err != nil {
		return "", fmt.Errorf("error copying file %s:%w", logHandle.Name(), err)

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Ensure the collector user can read all files in the log directory
  2. Disable/retry around log rotation while collecting (re-run after rotation completes)
  3. Re-run the diagnostic; transient races usually resolve on retry

Example fix

// before
cloudflared diagnostic collect   # fails on file deleted mid-run
// after
# stop/retry after rotation window, or chown log dir to collector user
chown -R cloudflared:cloudflared /var/log/cloudflared
Defensive patterns

Strategy: retry

Validate before calling

// best-effort pre-check that entries are readable
entries, _ := os.ReadDir(logDir)
for _, e := range entries {
	if f, err := os.Open(filepath.Join(logDir, e.Name())); err == nil { f.Close() } else { /* warn */ }
}

Try / catch

out, err := diagnostic.CopyFilesFromDirectory(ctx, fs, logDir, logFilename)
if err != nil && strings.Contains(err.Error(), "error opening file") {
	time.Sleep(time.Second) // let rotation settle
	out, err = diagnostic.CopyFilesFromDirectory(ctx, fs, logDir, logFilename)
}

Prevention

When it happens

Trigger: os.Open(filepath.Join(path, file.Name())) fails for one of the files listed by ReadDir — typically permission changes, or the file was deleted between ReadDir and Open (rotation race).

Common situations: Log rotation removing files mid-collection; mixed-permission files in the log directory; dangling entries.

Understand the failure class

Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.

Related errors


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/22e90b11b0e4c9ec. Report an issue: GitHub.