Billionmail/BillionMail · error
failed to save private key: %v
Error message
failed to save private key: %v
What it means
This error wraps the underlying filesystem failure that occurred while writing the ACME account private key to disk in AcmeCLI.Apply. After saving the certificate succeeds, the private key is written via public.WriteFile; any I/O error (permissions, missing directory, disk full) is wrapped with this message. It aborts the certificate issuance flow, returning empty paths.
Source
Thrown at core/internal/service/acme/cli.go:210
fmt.Printf(" Valid from: %s\n", certInfo.NotBefore)
fmt.Printf(" Valid to: %s\n", certInfo.NotAfter)
fmt.Printf(" Domains: %s\n", strings.Join(certInfo.DNSNames, ", "))
// Certificate files
certificatePath := filepath.Join(cli.OutputPath, "certificate.pem")
privateKeyPath := filepath.Join(cli.OutputPath, "private_key.pem")
// Save certificate and private key to files
_, err = public.WriteFile(certificatePath, certificate)
if err != nil {
return "", "", fmt.Errorf("failed to save certificate: %v", err)
}
_, err = public.WriteFile(privateKeyPath, privateKey)
if err != nil {
return "", "", fmt.Errorf("failed to save private key: %v", err)
}
fmt.Printf("Certificate saved to: %s\n", certificatePath)
fmt.Printf("Private key saved to: %s\n", privateKeyPath)
return certificatePath, privateKeyPath, nil
}
/**
* @brief Save certificate to database
* @return error
*/
func (cli *AcmeCLI) SaveToDatabase(accountId int, certificate, privateKey string) (int, error) {
// Get certificate info
certInfo := GetCertInfo(certificate)
if certInfo.Subject == "" {
return 0, fmt.Errorf("invalid certificate")
}View on GitHub (pinned to fc36c76c05)
Solutions
- Check the wrapped %v detail to identify the actual filesystem error
- Ensure the parent directory of privateKeyPath exists (os.MkdirAll) before calling Apply
- Run the process with sufficient permissions or chown the output directory to the service user
- Verify the disk is not full and the path is writable (touch a test file in that directory)
- Use an absolute, valid path for the private key output
Example fix
// before _, err = public.WriteFile(privatePath, privateKey) // after _ = os.MkdirAll(filepath.Dir(privateKeyPath), 0700) _, err = public.WriteFile(privateKeyPath, privateKey)
Defensive patterns
Strategy: try-catch
Validate before calling
if _, err := os.Stat(filepath.Dir(privateKeyPath)); err != nil {
if err := os.MkdirAll(filepath.Dir(privateKeyPath), 0700); err != nil { return err }
}
if f, err := os.OpenFile(privateKeyPath, os.O_CREATE|os.O_WRONLY, 0600); err != nil { return err } else { f.Close() } Try / catch
certPath, keyPath, err := cli.Apply(...)
if err != nil {
if strings.HasPrefix(err.Error(), "failed to save private key") {
log.Printf("key write failed: %v — check path permissions/disk", err)
}
return err
} Prevention
- Create the output directory with MkdirAll before Apply
- Run the service with a user that owns the cert/key directory
- Monitor disk space on the host storing certificates
- Use absolute paths for key/cert outputs
When it happens
Trigger: Calling Apply (directly or via applyCommand) when the target privateKeyPath directory does not exist, the process lacks write permission, the disk is full, or the path is invalid.
Common situations: Running the ACME CLI as a non-root user without write access to the config/cert directory; deploying in a container with a read-only filesystem; a typo in the configured key output path; parent directories never created before Apply runs.
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: %v
- failed to send confirmation email: %w
- Failed to save certificate file: {}
- Failed to save private key file: {}
- error reading project configuration file: %v
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/3ecb539132109138.
Report an issue: GitHub.