{"record":{"id":"76abd581cfe1de54","repo":"router-for-me/CLIProxyAPI","slug":"home-ca-certificate-file-is-missing","errorCode":null,"errorMessage":"home ca certificate file is missing","messagePattern":"home ca certificate file is missing","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/home/certificate.go","lineNumber":136,"sourceCode":"\nfunc defaultCertificatePaths() (certificatePaths, error) {\n\thomeDir, errHome := os.UserHomeDir()\n\tif errHome != nil {\n\t\treturn certificatePaths{}, errHome\n\t}\n\tdir := filepath.Join(homeDir, \".cli-proxy-api\")\n\treturn certificatePaths{\n\t\tDir:        dir,\n\t\tClientCert: filepath.Join(dir, \"client-crt.pem\"),\n\t\tClientKey:  filepath.Join(dir, \"client-key.pem\"),\n\t\tCACert:     filepath.Join(dir, \"home-ca-crt.pem\"),\n\t}, nil\n}\n\nfunc ensureHomeCertificateFiles(ctx context.Context, claims homeJWTClaims, paths certificatePaths) error {\n\tif fileExists(paths.ClientCert) && fileExists(paths.ClientKey) {\n\t\tif !fileExists(paths.CACert) {\n\t\t\treturn fmt.Errorf(\"home ca certificate file is missing\")\n\t\t}\n\t\tif errVerify := verifyCACertificateFile(paths.CACert, claims.CAFingerprint); errVerify != nil {\n\t\t\treturn errVerify\n\t\t}\n\t\tif errChmod := chmodCertificateFiles(paths); errChmod != nil {\n\t\t\treturn errChmod\n\t\t}\n\t\treturn nil\n\t}\n\tif errMkdir := os.MkdirAll(paths.Dir, 0o700); errMkdir != nil {\n\t\treturn errMkdir\n\t}\n\tkey, errKey := loadOrCreateClientKey(paths.ClientKey)\n\tif errKey != nil {\n\t\treturn errKey\n\t}\n\tcsrPEM, errCSR := createClientCSR(claims.CertificateID, key)\n\tif errCSR != nil {","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/home/certificate.go#L118-L154","documentation":"Consistency check in ensureHomeCertificateFiles: the client certificate and key files exist on disk, but the home CA certificate file is missing, so the mTLS triple is incomplete and the existing client material cannot be trusted/verified against the pinned fingerprint.","triggerScenarios":"Under ~/.cli-proxy-api, client-crt.pem and client-key.pem exist but home-ca-crt.pem was deleted, never written (partial enrollment crash between file writes), or excluded by a backup/sync tool.","commonSituations":"A previous enrollment run was interrupted after writing some files, someone cleaned up 'unused' PEM files, or a dotfile-sync/backup tool skipped the CA file.","solutions":["Delete ~/.cli-proxy-api/client-crt.pem and ~/.cli-proxy-api/client-key.pem and re-enroll so all three files are written together","Or restore home-ca-crt.pem from backup and confirm it matches the ca_fingerprint in the enrollment token","Check permissions/disk-full causes if enrollment keeps dying mid-write (files are written 0600)"],"exampleFix":"# before: partial state\n~/.cli-proxy-api/client-crt.pem   # exists\n~/.cli-proxy-api/client-key.pem   # exists\n~/.cli-proxy-api/home-ca-crt.pem  # MISSING -> error\n\n# after: re-enroll with a fresh token\nrm ~/.cli-proxy-api/client-crt.pem ~/.cli-proxy-api/client-key.pem\n# restart with the enrollment token; all three files are recreated","handlingStrategy":"validation","validationCode":"func certTripleComplete(dir string) bool {\n    for _, f := range []string{\"client-crt.pem\", \"client-key.pem\", \"home-ca-crt.pem\"} {\n        if _, err := os.Stat(filepath.Join(dir, f)); err != nil {\n            return false\n        }\n    }\n    return true\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat the three PEM files as one unit: restore or delete all together","Exclude ~/.cli-proxy-api from partial backup/sync jobs that might skip one file","After enrollment, verify all three files exist and are 0600 before relying on them"],"tags":["mtls","certificates","enrollment","home","filesystem"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}