{"record":{"id":"00cdc538613b5143","repo":"router-for-me/CLIProxyAPI","slug":"home-tls-read-ca-cert-w","errorCode":null,"errorMessage":"home tls: read ca-cert: %w","messagePattern":"home tls: read ca-cert: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/home/client.go","lineNumber":653,"sourceCode":"\tif clientCertPath != \"\" || clientKeyPath != \"\" {\n\t\tif clientCertPath == \"\" || clientKeyPath == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"home tls: client certificate and key must be set together\")\n\t\t}\n\t\tcertPair, errLoad := tls.LoadX509KeyPair(clientCertPath, clientKeyPath)\n\t\tif errLoad != nil {\n\t\t\treturn nil, fmt.Errorf(\"home tls: load client certificate: %w\", errLoad)\n\t\t}\n\t\ttlsConfig.Certificates = []tls.Certificate{certPair}\n\t}\n\n\tcaCertPath := strings.TrimSpace(cfg.CACert)\n\tif caCertPath == \"\" {\n\t\treturn tlsConfig, nil\n\t}\n\n\tcaCertPEM, errRead := os.ReadFile(caCertPath)\n\tif errRead != nil {\n\t\treturn nil, fmt.Errorf(\"home tls: read ca-cert: %w\", errRead)\n\t}\n\n\tcertPool, errPool := x509.SystemCertPool()\n\tif errPool != nil || certPool == nil {\n\t\tcertPool = x509.NewCertPool()\n\t}\n\tif !certPool.AppendCertsFromPEM(caCertPEM) {\n\t\treturn nil, fmt.Errorf(\"home tls: ca-cert contains no PEM certificates\")\n\t}\n\ttlsConfig.RootCAs = certPool\n\n\treturn tlsConfig, nil\n}\n\nfunc (c *Client) commandClient() (*redis.Client, error) {\n\tif c == nil || c.dispatchFenced.Load() {\n\t\treturn nil, ErrDispatchFenced\n\t}","sourceCodeStart":635,"sourceCodeEnd":671,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/home/client.go#L635-L671","documentation":"Wraps os.ReadFile failure in internal/home/client.go when reading the configured CA certificate file for the home TLS root pool. The %w preserves the os error — almost always 'no such file or directory' or 'permission denied' for the ca-cert path.","triggerScenarios":"home.tls.ca-cert points at a path that does not exist at runtime, or exists but is not readable by the process user; relative path resolved against a different working directory in a container/service.","commonSituations":"CA not yet distributed to the node; path typo or changed mount point in Kubernetes (secret not mounted); service running with a different WORKDIR so a relative path breaks; file owned root-only.","solutions":["Verify the exact path exists from the process's perspective: ls -l <path> as the service user","Use absolute paths in config to avoid working-directory dependence","Fix permissions (0644 readable) or ownership if it is a permission error","If the CA was never copied, distribute it from the home server"],"exampleFix":"# before\nhome:\n  tls:\n    ca-cert: ca.pem  # relative, breaks under systemd/container\n\n# after\nhome:\n  tls:\n    ca-cert: /etc/cliproxy/ca.pem","handlingStrategy":"validation","validationCode":"if cfg.TLS.CACert != \"\" {\n    if _, err := os.Stat(cfg.TLS.CACert); err != nil {\n        return fmt.Errorf(\"home ca-cert %s not accessible: %w\", cfg.TLS.CACert, err)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err != nil && errors.Is(err, fs.ErrNotExist) {\n    log.Errorf(\"ca-cert path %s missing — distribute CA or fix mount\", cfg.TLS.CACert)\n}","preventionTips":["Use absolute paths for all TLS material","Make secret mounts mandatory (not optional) so missing mounts fail loudly at deploy"],"tags":["go","tls","filesystem","configuration","home"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}