Billionmail/BillionMail · error
failed to write DKIM signing config: %v
Error message
failed to write DKIM signing config: %v
What it means
RepairDKIMSigningConfig regenerates the Rspamd DKIM signing configuration block and overwrites the signing config file via public.WriteFile. This error wraps any failure from that write, meaning the new DKIM config content could not be persisted to disk.
Source
Thrown at core/internal/service/domains/domains.go:973
#%s_DKIM_END
`, d.Domain, d.Domain, d.Domain, d.Domain, d.Domain)
allSignConfBlocks.WriteString(signConf)
}
// 3. Construct the final dkim_signing.conf content
signConfPath := public.AbsPath(filepath.Join(consts.RSPAMD_LOCAL_D_PATH, "dkim_signing.conf"))
finalSignContent := fmt.Sprintf(`sign_headers = "from:sender:reply-to:subject:date:message-id:to:cc:mime-version:content-type:content-transfer-encoding:content-language:resent-to:resent-cc:resent-from:resent-sender:resent-message-id:in-reply-to:references:list-id:list-help:list-owner:list-unsubscribe:list-subscribe:list-post:list-unsubscribe-post:disposition-notification-to:disposition-notification-options:original-recipient:openpgp:autocrypt";
domain {
#BT_DOMAIN_DKIM_BEGIN
%s
#BT_DOMAIN_DKIM_END
}`, allSignConfBlocks.String())
// 4. Write the new content to the file, overwriting the old one
_, err = public.WriteFile(signConfPath, finalSignContent)
if err != nil {
return fmt.Errorf("failed to write DKIM signing config: %v", err)
}
// 5. Ensure correct file permissions
err = filepath.Walk(filepath.Join(public.AbsPath(consts.RSPAMD_LIB_PATH), "dkim"), func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return os.Chmod(path, 0755)
}
if strings.HasSuffix(path, ".private") || strings.HasSuffix(path, ".pub") {
return os.Chmod(path, 0644)
}
return nil
})
if err != nil {
return fmt.Errorf("failed to change DKIM file permissions: %v", err)
}View on GitHub (pinned to fc36c76c05)
Solutions
- Verify the signing config path (derived from RSPAMD_LIB_PATH / rspamd conf dir) exists and is writable by the process user
- Check disk space (df -h) and filesystem mount status (mount ro?)
- Ensure the rspamd conf volume is mounted and the process runs with sufficient privileges (or chown the conf dir)
- Inspect the wrapped %v error for the underlying OS cause (e.g. permission denied vs no such file)
Example fix
// before
_, err = public.WriteFile(signConfPath, finalSignContent)
if err != nil {
return fmt.Errorf("failed to write DKIM signing config: %v", err)
}
// after
if err := os.MkdirAll(filepath.Dir(signConfPath), 0755); err != nil {
return fmt.Errorf("failed to prepare dkim conf dir: %v", err)
}
_, err = public.WriteFile(signConfPath, finalSignContent)
if err != nil {
return fmt.Errorf("failed to write DKIM signing config %s: %v", signConfPath, err)
} Defensive patterns
Strategy: validation
Validate before calling
if fi, err := os.Stat(filepath.Dir(signConfPath)); err != nil || !fi.IsDir() {
return fmt.Errorf("dkim conf dir missing: %s", filepath.Dir(signConfPath))
}
if f, err := os.OpenFile(signConfPath, os.O_WRONLY, 0644); err != nil {
return fmt.Errorf("signing config not writable: %v", err)
} else {
f.Close()
} Try / catch
err := RepairDKIMSigningConfig(ctx)
if err != nil && strings.HasPrefix(err.Error(), "failed to write DKIM signing config") {
g.Log().Errorf(ctx, "check rspamd conf mount/permissions: %v", err)
} Prevention
- Bind-mount the rspamd conf directory read-write into the app container
- Run the app as a user with write access to the conf dir
- Monitor disk space on the conf volume
- Include the failing path in wrapped error messages
When it happens
Trigger: public.WriteFile(signConfPath, finalSignContent) returns non-nil: the signing config path is unwritable (permissions), the directory is missing, the filesystem is full/read-only, or the path resolves outside the container's mounted volume.
Common situations: Rspamd conf directory not bind-mounted into the app container; running the process as non-root without write access to /etc/rspamd or the RSPAMD_LIB_PATH volume; disk full on host; SELinux/AppArmor denying writes.
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 write DKIM sign config: %v
- Failed to write DKIM public key: %v
- Failed to read DKIM sign config: %v
- Cannot read DKIM public key: %v
- Failed to generate DKIM key pair: %v
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/0b2aa4fc3b7e5748.
Report an issue: GitHub.