{"record":{"id":"116a1cb2a417ec24","repo":"siyuan-note/siyuan","slug":"failed-to-write-ca-certificate-w","errorCode":null,"errorMessage":"failed to write CA certificate: %w","messagePattern":"failed to write CA certificate: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/util/cert.go","lineNumber":344,"sourceCode":"\tif !caCert.IsCA {\n\t\treturn fmt.Errorf(\"the provided certificate is not a CA certificate\")\n\t}\n\n\tkeyBlock, _ := pem.Decode([]byte(caKeyPEM))\n\tif keyBlock == nil {\n\t\treturn fmt.Errorf(\"failed to decode CA private key PEM\")\n\t}\n\n\t_, err = x509.ParseECPrivateKey(keyBlock.Bytes)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse CA private key: %w\", err)\n\t}\n\n\tcaCertPath := filepath.Join(ConfDir, TLSCACertFilename)\n\tcaKeyPath := filepath.Join(ConfDir, TLSCAKeyFilename)\n\n\tif err := os.WriteFile(caCertPath, []byte(caCertPEM), 0644); err != nil {\n\t\treturn fmt.Errorf(\"failed to write CA certificate: %w\", err)\n\t}\n\n\tif err := os.WriteFile(caKeyPath, []byte(caKeyPEM), 0600); err != nil {\n\t\treturn fmt.Errorf(\"failed to write CA private key: %w\", err)\n\t}\n\n\tcertPath := filepath.Join(ConfDir, TLSCertFilename)\n\tkeyPath := filepath.Join(ConfDir, TLSKeyFilename)\n\n\tif gulu.File.IsExist(certPath) {\n\t\tos.Remove(certPath)\n\t}\n\tif gulu.File.IsExist(keyPath) {\n\t\tos.Remove(keyPath)\n\t}\n\n\tlogging.LogInfof(\"imported CA bundle, server certificate will be regenerated on next TLS initialization\")\n\treturn nil","sourceCodeStart":326,"sourceCodeEnd":362,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/util/cert.go#L326-L362","documentation":"Returned by ImportCABundle when os.WriteFile fails writing caCertPEM to <ConfDir>/ca.crt (mode 0644). The PEM was validated and parsed, but persisting it to disk failed. The error wraps the underlying os PathError so the caller can inspect errno.","triggerScenarios":"Calling ImportCABundle when the conf directory does not exist, is read-only, the disk is full, or permission on ca.crt denies writing.","commonSituations":"ConfDir not initialised (kernel not booted); running with insufficient filesystem permissions; read-only deployment; out-of-disk.","solutions":["Ensure ConfDir (the workspace conf directory) exists and is writable before importing.","Free disk space or fix permissions on the conf directory and any existing ca.crt.","Inspect the wrapped error (errors.Unwrap) for the underlying os error and address that (ENOENT, EROFS, ENOSPC)."],"exampleFix":"// before\nerr := util.ImportCABundle(certPEM, keyPEM) // -> failed to write CA certificate: open .../ca.crt: permission denied\n\n// after\nif err := os.MkdirAll(util.ConfDir, 0755); err != nil { return err }\nerr := util.ImportCABundle(certPEM, keyPEM)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := util.ImportCABundle(certPEM, keyPEM); err != nil {\n    var pathErr *os.PathError\n    if errors.As(err, &pathErr) || strings.Contains(err.Error(), \"failed to write CA certificate\") {\n        // conf dir missing/readonly/full — fix the FS then re-run\n        os.MkdirAll(util.ConfDir, 0755)\n        return util.ImportCABundle(certPEM, keyPEM)\n    }\n    return err\n}","preventionTips":["Ensure ConfDir exists and is writable before importing.","Free disk space and fix permissions on the conf directory up front.","Inspect the wrapped os error to distinguish ENOENT, EROFS, ENOSPC."],"tags":["tls","cert","filesystem","io","ca"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}