{"record":{"id":"3b1de4d7733b09f4","repo":"Netflix/chaosmonkey","slug":"failed-to-read-file-s","errorCode":null,"errorMessage":"failed to read file %s","messagePattern":"failed to read file (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"spinnaker/spinnaker.go","lineNumber":151,"sourceCode":"\treturn New(spinnakerEndpoint, certPath, password, x509Cert, x509Key, user)\n\n}\n\n// New returns a Spinnaker using a .p12 cert at certPath encrypted with\n// password or x509 cert. The user argument identifies the email address of the user which is\n// sent in the payload of the terminateInstances task API call\nfunc New(endpoint string, certPath string, password string, x509Cert string, x509Key string, user string) (Spinnaker, error) {\n\tvar client *http.Client\n\tvar err error\n\n\tif x509Cert != \"\" && certPath != \"\" {\n\t\treturn Spinnaker{}, errors.New(\"cannot use both p12 and x509 certs, choose one\")\n\t}\n\n\tif certPath != \"\" {\n\t\tpfxData, err := ioutil.ReadFile(certPath)\n\t\tif err != nil {\n\t\t\treturn Spinnaker{}, errors.Wrapf(err, \"failed to read file %s\", certPath)\n\t\t}\n\n\t\tclient, err = getClient(pfxData, password)\n\t\tif err != nil {\n\t\t\treturn Spinnaker{}, err\n\t\t}\n\t} else if x509Cert != \"\" {\n\t\tclient, err = getClientX509(x509Cert, x509Key)\n\t\tif err != nil {\n\t\t\treturn Spinnaker{}, err\n\t\t}\n\t} else {\n\t\tclient = new(http.Client)\n\t}\n\n\treturn Spinnaker{endpoint: endpoint, client: client, user: user}, nil\n}\n","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/Netflix/chaosmonkey/blob/eaa28fb761c0ebe8644d1333e5d164e9cc3071e9/spinnaker/spinnaker.go#L133-L169","documentation":"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>\".","triggerScenarios":"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.","commonSituations":"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.","solutions":["Verify the path exists: `ls -l <certPath>` (and that it is a regular file, not a directory)","Fix the spinnaker.certificate path in the chaosmonkey config file or environment to the actual .p12 location","Fix permissions so the chaosmonkey process user can read it (`chown`/`chmod`, e.g. chmod 640 with proper group)","If running in a container/k8s, confirm the secret/volume mounting the cert is present at the expected path"],"exampleFix":"// before\ncfg: spinnaker:\n  certificate: /etc/certs/spinnaker.p12   # file not present in container\n// after\n# k8s: mount the secret, then\nvolumes:\n  - name: spinnaker-cert\n    secret:\n      secretName: spinnaker-cert\nvolumeMounts:\n  - name: spinnaker-cert\n    mountPath: /etc/certs\n# config\ncertificate: /etc/certs/spinnaker.p12","handlingStrategy":"validation","validationCode":"if certPath != \"\" {\n\tinfo, err := os.Stat(certPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"cert file %s not accessible: %w\", certPath, err)\n\t}\n\tif info.IsDir() {\n\t\treturn fmt.Errorf(\"%s is a directory, expected a .p12 file\", certPath)\n\t}\n\tf, err := os.Open(certPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"no read permission for %s: %w\", certPath, err)\n\t}\n\tf.Close()\n}","typeGuard":null,"tryCatchPattern":"sp, err := spinnaker.New(endpoint, certPath, password, \"\", \"\", user)\nif err != nil {\n\tvar pathErr *fs.PathError\n\tif errors.As(err, &pathErr) || strings.Contains(err.Error(), \"failed to read file\") {\n\t\treturn fmt.Errorf(\"cert path %s missing or unreadable; fix config/mount/permissions: %w\", certPath, err)\n\t}\n\treturn err\n}","preventionTips":["Use absolute paths in config and verify with `ls -l` as the same user chaosmonkey runs as","In containers, confirm the secret/volume is mounted before startup (readiness checks)","Check file permissions (chmod/chown) whenever certs are rotated","Fail fast at config-load time: stat the cert path when parsing config, not at first API call"],"tags":["go","filesystem","certificate","config"],"backgroundTag":"file-not-found","analyzedSha":"eaa28fb761c0ebe8644d1333e5d164e9cc3071e9","analyzedAt":"2026-09-03T17:04:39.020Z","contentChangedAt":"2026-09-03T17:04:39.020Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}