Billionmail/BillionMail · error
Failed to save private key file: {}
Error message
Failed to save private key file: {} What it means
Thrown in ApplySSLWithExistingServer when public.WriteFile fails to persist private_key.pem into savePath, after certificate.pem was written successfully. It wraps the raw OS error so the actual cause (permissions, disk full, path issues) is in the message.
Source
Thrown at core/internal/service/acme/acme.go:489
if !public.FileExists(savePath) {
err = os.MkdirAll(savePath, 0750)
if err != nil {
return "", "", errors.New(public.LangCtx(ctx, "Failed to create directory: {}", err.Error()))
}
}
// Save certificate and private key files
certificateFile := filepath.Join(savePath, "certificate.pem")
privateKeyFile := filepath.Join(savePath, "private_key.pem")
_, err = public.WriteFile(certificateFile, string(certificates.Certificate))
if err != nil {
return "", "", errors.New(public.LangCtx(ctx, "Failed to save certificate file: {}", err.Error()))
}
_, err = public.WriteFile(privateKeyFile, string(certificates.PrivateKey))
if err != nil {
return "", "", errors.New(public.LangCtx(ctx, "Failed to save private key file: {}", err.Error()))
}
}
// Return certificate
return string(certificates.Certificate), string(certificates.PrivateKey), nil
}
type CertInfo v1.CertInfo
/**
* @description: Get certificate information
* @param {string} certificateStr Certificate string
* @return {CertInfo} Certificate information
*/
func GetCertInfo(certificateStr string) CertInfo {
certInfo := CertInfo{}
block, _ := pem.Decode([]byte(certificateStr))
if block == nil {View on GitHub (pinned to fc36c76c05)
Solutions
- Read the embedded OS error and fix the filesystem condition (permissions, disk space)
- Verify the process can create files in savePath (touch a test file as the service user)
- Free disk space / raise quota if 'no space left on device' is reported
- Ensure nothing removes or chmods savePath between the certificate and key writes
Example fix
// before
// cert dir writable only by root; service runs as mailuser
_, _, err = svc.ApplySSLWithExistingServer(ctx, d, keyType, c, k, "/etc/ssl/private")
// after
os.Chown("/etc/ssl/private/mailuser", uid, gid) // or use a dedicated dir owned by the service user
_, _, err = svc.ApplySSLWithExistingServer(ctx, d, keyType, c, k, "/etc/ssl/private/mailuser") Defensive patterns
Strategy: validation
Validate before calling
if err := os.MkdirAll(savePath, 0750); err != nil { return err }
if err := unix.Access(savePath, unix.W_OK); err != nil { return fmt.Errorf("%s not writable: %w", savePath, err) }
// ensure free space for both files
if st, err := os.Statfs(savePath); err == nil && st.Bavail*uint64(st.Bsize) < 64*1024 { return errors.New("insufficient space for key material") } Try / catch
if _, _, err := svc.ApplySSLWithExistingServer(ctx, d, kt, c, k, savePath); err != nil {
if strings.Contains(err.Error(), "private key") {
log.Printf("key persistence failed for %s: %v", savePath, err)
// cert.pem may exist; clean up partial state before retry
os.Remove(filepath.Join(savePath, "certificate.pem"))
}
return err
} Prevention
- Verify writability of savePath as the service user before issuance
- Monitor disk usage; key writes fail on full volumes
- Avoid concurrent jobs chmod/chown the directory mid-write
- Use restrictive-but-owned dirs (0750, service user) for key material
When it happens
Trigger: ApplySSLWithExistingServer calls public.WriteFile(privateKeyFile, string(certificates.PrivateKey)) and the OS write fails — typically same causes as the certificate write: permissions, full disk, directory removed mid-operation.
Common situations: Save directory ownership changed between writes by an external sync; quota exceeded mid-write; disk filled up by the preceding certificate write in a constrained container.
Understand the failure class
Background: "Permission denied" / "Failed to write" file errors: why a library can't write its files to disk (EACCES, EPERM, ENOSPC) and how to fix them — this error's family across 43 libraries.
Related errors
- Failed to save certificate file: {}
- failed to write key file: %v
- Failed to create directory: {}
- failed to save certificate: %v
- failed to save private key: %v
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/da17d851fa9ae9b1.
Report an issue: GitHub.