cloudflare/cloudflared · error

unable to read the file %s for --%s

Error message

unable to read the file %s for --%s

What it means

Wrapped os.ReadFile failure in tlsconfig.LoadOriginCA: the file given via --origin-ca-pool could not be read (missing path, permission denied, or is a directory), so the custom origin CA pool cannot be built and origin TLS configuration fails early.

Source

Thrown at tlsconfig/origin_ca.go:27

	"runtime"

	"github.com/pkg/errors"
	"github.com/rs/zerolog"
)

const (
	OriginCAPoolFlag = "origin-ca-pool"
)

func LoadOriginCA(originCAPoolFilename string, log *zerolog.Logger) (*x509.CertPool, error) {
	var originCustomCAPool []byte

	if originCAPoolFilename != "" {
		var err error
		// nolint:gosec
		originCustomCAPool, err = os.ReadFile(originCAPoolFilename)
		if err != nil {
			return nil, errors.Wrap(err, fmt.Sprintf("unable to read the file %s for --%s", originCAPoolFilename, OriginCAPoolFlag))
		}
	}

	originCertPool, err := loadOriginCertPool(originCustomCAPool, log)
	if err != nil {
		return nil, errors.Wrap(err, "error loading the certificate pool")
	}

	// Windows users should be notified that they can use the flag
	if runtime.GOOS == "windows" && originCAPoolFilename == "" {
		log.Info().Msgf("cloudflared does not support loading the system root certificate pool on Windows. Please use --%s <PATH> to specify the path to the certificate pool", OriginCAPoolFlag)
	}

	return originCertPool, nil
}

func LoadCustomOriginCA(originCAFilename string) (*x509.CertPool, error) {
	// First, obtain the system certificate pool

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Verify the path exists and is readable: ls -l <path> and test with `cat`
  2. Use an absolute path for --origin-ca-pool
  3. Mount/copy the CA file into containers and ensure the runtime user can read it
  4. Fix permissions (chmod/chown) if access is denied

Example fix

// before
originCAPool = "/etc/cloudflared/origin-ca.pem" // file not mounted in container
// after
if _, err := os.Stat(originCAPool); err != nil {
    log.Fatal().Err(err).Msg("--origin-ca-pool file missing")
}
// ensure volume mount: -v /etc/cloudflared/origin-ca.pem:/etc/cloudflared/origin-ca.pem:ro
Defensive patterns

Strategy: validation

Validate before calling

// before starting cloudflared with --origin-ca-pool
if info, err := os.Stat(path); err != nil {
    return fmt.Errorf("origin CA pool missing: %w", err)
} else if info.IsDir() {
    return fmt.Errorf("origin CA pool is a directory: %s", path)
}
f, err := os.Open(path)
if err != nil {
    return fmt.Errorf("origin CA pool unreadable: %w", err)
}
f.Close()

Try / catch

pool, err := tlsconfig.LoadOriginCA(path, log)
if err != nil {
    if strings.Contains(err.Error(), "unable to read the file") {
        return fmt.Errorf("check --origin-ca-pool path %q: %w", path, err)
    }
    return err
}

Prevention

When it happens

Trigger: newHTTPTransport calls LoadOriginCA with a non-empty originCAPoolFilename that os.ReadFile cannot read: nonexistent path, no read permission, or path is a directory.

Common situations: Typo in --origin-ca-pool path; running cloudflared in a container without the file mounted; wrong user/permissions; relative path resolving differently due to working directory.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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