Netflix/chaosmonkey · error

failed to read file %s

Error message

failed to read file %s

What it means

spinnaker.New reads the .p12 certificate file at certPath with ioutil.ReadFile before building the mTLS client. This error means the file could not be read at all — it does not exist, the path is wrong, or the process lacks permission. The OS error is wrapped with "failed to read file <path>".

Source

Thrown at spinnaker/spinnaker.go:151

	return New(spinnakerEndpoint, certPath, password, x509Cert, x509Key, user)

}

// New returns a Spinnaker using a .p12 cert at certPath encrypted with
// password or x509 cert. The user argument identifies the email address of the user which is
// sent in the payload of the terminateInstances task API call
func New(endpoint string, certPath string, password string, x509Cert string, x509Key string, user string) (Spinnaker, error) {
	var client *http.Client
	var err error

	if x509Cert != "" && certPath != "" {
		return Spinnaker{}, errors.New("cannot use both p12 and x509 certs, choose one")
	}

	if certPath != "" {
		pfxData, err := ioutil.ReadFile(certPath)
		if err != nil {
			return Spinnaker{}, errors.Wrapf(err, "failed to read file %s", certPath)
		}

		client, err = getClient(pfxData, password)
		if err != nil {
			return Spinnaker{}, err
		}
	} else if x509Cert != "" {
		client, err = getClientX509(x509Cert, x509Key)
		if err != nil {
			return Spinnaker{}, err
		}
	} else {
		client = new(http.Client)
	}

	return Spinnaker{endpoint: endpoint, client: client, user: user}, nil
}

View on GitHub (pinned to eaa28fb761)

Solutions

  1. Verify the path exists: `ls -l <certPath>` (and that it is a regular file, not a directory)
  2. Fix the spinnaker.certificate path in the chaosmonkey config file or environment to the actual .p12 location
  3. Fix permissions so the chaosmonkey process user can read it (`chown`/`chmod`, e.g. chmod 640 with proper group)
  4. If running in a container/k8s, confirm the secret/volume mounting the cert is present at the expected path

Example fix

// before
cfg: spinnaker:
  certificate: /etc/certs/spinnaker.p12   # file not present in container
// after
# k8s: mount the secret, then
volumes:
  - name: spinnaker-cert
    secret:
      secretName: spinnaker-cert
volumeMounts:
  - name: spinnaker-cert
    mountPath: /etc/certs
# config
certificate: /etc/certs/spinnaker.p12
Defensive patterns

Strategy: validation

Validate before calling

if certPath != "" {
	info, err := os.Stat(certPath)
	if err != nil {
		return fmt.Errorf("cert file %s not accessible: %w", certPath, err)
	}
	if info.IsDir() {
		return fmt.Errorf("%s is a directory, expected a .p12 file", certPath)
	}
	f, err := os.Open(certPath)
	if err != nil {
		return fmt.Errorf("no read permission for %s: %w", certPath, err)
	}
	f.Close()
}

Try / catch

sp, err := spinnaker.New(endpoint, certPath, password, "", "", user)
if err != nil {
	var pathErr *fs.PathError
	if errors.As(err, &pathErr) || strings.Contains(err.Error(), "failed to read file") {
		return fmt.Errorf("cert path %s missing or unreadable; fix config/mount/permissions: %w", certPath, err)
	}
	return err
}

Prevention

When it happens

Trigger: Calling spinnaker.New (directly or via NewFromConfig) with a non-empty certPath that points to a missing file, a directory, or a file the process cannot read (permissions), including broken symlinks and unmounted volumes.

Common situations: Wrong path in chaosmonkey config (spinnaker.certificate); cert file not baked into/mounted in the container; running under a different user than the cert owner; typo or stale path after cert rotation.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of Netflix/chaosmonkey@eaa28fb761 (2026-09-03). Data as JSON: /api/errors/3b1de4d7733b09f4. Report an issue: GitHub.