{"record":{"id":"f9ef8138c599df7f","repo":"gofiber/fiber","slug":"failed-to-read-client-ca-file-q-w","errorCode":null,"errorMessage":"failed to read client CA file %q: %w","messagePattern":"failed to read client CA file %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"listen.go","lineNumber":399,"sourceCode":"\tlog.Warnf(\"[Listener] serves the supplied listener as-is, so %s %s ignored%s\",\n\t\tstrings.Join(ignored, \", \"), pluralIsAre(len(ignored)), suffix)\n}\n\nfunc pluralIsAre(n int) string {\n\tif n == 1 {\n\t\treturn \"is\"\n\t}\n\treturn \"are\"\n}\n\nfunc applyClientCert(tlsConfig *tls.Config, certClientFile string) error {\n\tif certClientFile == \"\" {\n\t\treturn nil\n\t}\n\n\tclientCACert, err := os.ReadFile(filepath.Clean(certClientFile))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read client CA file %q: %w\", certClientFile, err)\n\t}\n\n\tclientCertPool := x509.NewCertPool()\n\tif ok := clientCertPool.AppendCertsFromPEM(clientCACert); !ok {\n\t\treturn fmt.Errorf(\"failed to parse client CA certificate from %q\", certClientFile)\n\t}\n\n\ttlsConfig.ClientAuth = tls.RequireAndVerifyClientCert\n\ttlsConfig.ClientCAs = clientCertPool\n\n\treturn nil\n}\n\n// Listener serves HTTP requests from the given listener.\n// You should enter custom ListenConfig to customize startup. (prefork, startup message, graceful shutdown...)\n//\n// The listener is served exactly as supplied, so every TLS field of the config\n// is ignored — including CertClientFile. Wrap it with tls.NewListener yourself","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/listen.go#L381-L417","documentation":"Returned by applyClientCert when os.ReadFile fails to read the file pointed to by ListenConfig.CertClientFile. Fiber reads this PEM file to populate the client CA pool used for mutual TLS (tls.RequireAndVerifyClientCert). The wrapped error preserves the underlying os/fs error (ENOENT, EACCES, EISDIR, etc.).","triggerScenarios":"App.Listen or App.ListenTLS is called with ListenConfig.CertClientFile set to a path that does not exist, is unreadable under the process's UID/GID, is a directory, or lives on an unmounted filesystem. The error fires before any listener is created, during createListener -> applyClientCert.","commonSituations":"Deploying behind mTLS with a path that works in dev but is missing in the container image; running the binary as a non-root user that cannot read a root-owned CA file; relative path resolved against the wrong working directory; typo in the env var feeding CertClientFile (e.g. $TLS_CA_CERT vs $TLS_CLIENT_CERT).","solutions":["Verify the path exists and is a regular file: ls -l <path> and file <path>.","Check the process can read it under the runtime user: sudo -u <user> cat <path> >/dev/null.","Use an absolute path for CertClientFile; never rely on the service's working directory.","If running in systemd/Docker, confirm the file is COPY'd/ADD'd into the image and the volume is mounted read-only.","Ensure the file is PEM-encoded; a DER cert will pass ReadFile but fail later at AppendCertsFromPEM (error 121)."],"exampleFix":"// before\ncfg := fiber.ListenConfig{CertClientFile: \"ca.pem\"} // relative, missing in prod\napp.Listen(\":443\", cfg)\n\n// after\ncfg := fiber.ListenConfig{CertClientFile: \"/etc/fiber/tls/client-ca.pem\"}\napp.Listen(\":443\", cfg)","handlingStrategy":"validation","validationCode":"// Run before app.Listen to fail fast with a clearer message.\nfunc checkClientCAFile(path string) error {\n    if path == \"\" {\n        return nil // not configured; fiber skips mTLS\n    }\n    abs, err := filepath.Abs(path)\n    if err != nil {\n        return fmt.Errorf(\"resolve CertClientFile path: %w\", err)\n    }\n    info, err := os.Stat(abs)\n    if err != nil {\n        return fmt.Errorf(\"CertClientFile unreadable: %w\", err)\n    }\n    if info.IsDir() {\n        return fmt.Errorf(\"CertClientFile %q is a directory\", abs)\n    }\n    if info.Mode().Perm()&0o400 == 0 {\n        return fmt.Errorf(\"CertClientFile %q not readable by current user\", abs)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always use absolute paths for CertClientFile.","Run the service under the same user that owns the CA file, or chown it explicitly.","In Docker, COPY the CA file and chmod it in the image.","Add a pre-start readiness check that stats the file."],"tags":["tls","mtls","filesystem","startup","listen"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}