Billionmail/BillionMail · error

Failed to write DKIM public key: %v

Error message

Failed to write DKIM public key: %v

What it means

After key generation, the rspamadm output (public key text) is written to <selector>.pub on the host via public.WriteFile. This error wraps that write failure. The private key exists in the Rspamd volume but the public key file needed to build the DKIM DNS record is missing.

Source

Thrown at core/internal/service/domains/domains.go:563

	}
	defer dk.Close()

	// Generate new keys if they don't exist
	if !public.FileExists(dkimPriPath) || !public.FileExists(dkimPubPath) {
		mutex.Lock()
		defer mutex.Unlock()

		var res *v2.ExecResult
		res, err = dk.ExecCommandByName(context.Background(), consts.SERVICES.Rspamd, []string{"rspamadm", "dkim_keygen", "-s", selector, "-b", fmt.Sprintf("%d", keySize), "-d", domain, "-k", fmt.Sprintf("/var/lib/rspamd/dkim/%s/%s.private", domain, selector)}, "root")
		if err != nil {
			err = fmt.Errorf("Failed to generate DKIM key pair: %v", err)
			return
		}

		if res != nil {
			_, err = public.WriteFile(dkimPubPath, res.Output)
			if err != nil {
				err = fmt.Errorf("Failed to write DKIM public key: %v", err)
				return
			}
		}

		// update dkim private key file permission to 0644
		err = os.Chmod(dkimPriPath, 0644)
		if err != nil {
			err = fmt.Errorf("Failed to change DKIM private key permissions: %v", err)
			return
		}

		// Skip DKIM signing config for relay-mapped domains — relay provider signs
		relayDomains, relayErr := GetRelayDomains(context.Background())
		if relayErr != nil {
			g.Log().Warning(context.Background(), "Failed to check relay domains for DKIM signing:", relayErr)
			relayDomains = make(map[string]bool)
		}

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Ensure the DKIM directory exists on the host (os.MkdirAll(dkimPath, 0755) before writing) and check the wrapped permission/disk error
  2. Verify rspamadm output was non-empty; re-run key generation if res.Output is empty
  3. Fix ownership/permissions on the dkim volume mount
  4. Re-run GetDKIMRecord to regenerate both keys if the pub file is corrupt

Example fix

// before
if res != nil {
    _, err = public.WriteFile(dkimPubPath, res.Output)
    if err != nil { err = fmt.Errorf("Failed to write DKIM public key: %v", err); return }
}
// after
if res == nil || len(strings.TrimSpace(res.Output)) == 0 {
    err = fmt.Errorf("rspamadm dkim_keygen produced no output")
    return
}
if err = os.MkdirAll(dkimPath, 0755); err != nil { return }
if _, err = public.WriteFile(dkimPubPath, res.Output); err != nil {
    err = fmt.Errorf("Failed to write DKIM public key to %s: %v", dkimPubPath, err)
    return
}
Defensive patterns

Strategy: validation

Validate before calling

if err := os.MkdirAll(dkimPath, 0755); err != nil { return fmt.Errorf("cannot create dkim dir: %v", err) }
if err := unix.Access(dkimPath, unix.W_OK); err != nil { return fmt.Errorf("dkim dir not writable: %v", err) }

Try / catch

if _, err := public.WriteFile(dkimPubPath, res.Output); err != nil {
    return fmt.Errorf("Failed to write DKIM public key %s: %v", dkimPubPath, err) // includes path context
}

Prevention

When it happens

Trigger: getDKIMRecordWithKeySize after successful dkim_keygen when public.WriteFile(dkimPubPath, res.Output) fails — dkim directory missing on host, permission denied, disk full, or res.Output empty because the exec result carried no output.

Common situations: Host-side dkimPath not created before WriteFile (missing os.MkdirAll); volume permission mismatch between rspamd container user and host; res==nil or empty output path silently producing a bad/empty pub file if not guarded (here guarded by res != nil but not by empty output).

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/7edf780bdabf978d. Report an issue: GitHub.