{"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/9f775e8a12daef8255556097396f9b2739078892/kernel/util/cert.go#L326-L362","documentation":"ImportCABundle writes the validated CA certificate PEM to <ConfDir>/TLSCACertFilename with mode 0644. This error wraps the os.WriteFile failure, so the cert was valid but could not be persisted to disk.","triggerScenarios":"os.WriteFile(caCertPath, ..., 0644) fails — typically because ConfDir does not exist, the workspace/config directory is read-only, or a filesystem/permission error occurs.","commonSituations":"Workspace on a read-only mount or full disk; running the kernel as a user without write access to the workspace conf directory; ConfDir removed or not yet initialized.","solutions":["Ensure the workspace conf directory exists and is writable by the kernel process user","Check disk space and that the volume is not mounted read-only","Fix directory ownership/permissions (e.g. chown/chmod) and retry the import"],"exampleFix":"// before\n// conf dir on read-only volume -> write fails\n// after\nos.MkdirAll(confDir, 0755) // ensure writable dir before ImportCABundle\nImportCABundle(caCertPEM, caKeyPEM)","handlingStrategy":"try-catch","validationCode":"func canWrite(dir string) error {\n    if err := os.MkdirAll(dir, 0755); err != nil { return err }\n    f, err := os.CreateTemp(dir, \".wtest\")\n    if err != nil { return err }\n    f.Close(); os.Remove(f.Name())\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if err := util.ImportCABundle(caCertPEM, caKeyPEM); err != nil {\n    var perr *fs.PathError\n    if errors.As(err, &perr) {\n        // inspect perr.Path / perr.Err: fix permissions or disk\n    }\n}","preventionTips":["Ensure the workspace conf directory exists and is writable before importing","Monitor disk space on the workspace volume","Run the kernel as a user that owns the workspace directory"],"tags":["tls","filesystem","file-write"],"backgroundTag":"file-write-failed","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}