{"record":{"id":"7edf780bdabf978d","repo":"Billionmail/BillionMail","slug":"failed-to-write-dkim-public-key-v","errorCode":null,"errorMessage":"Failed to write DKIM public key: %v","messagePattern":"Failed to write DKIM public key: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/domains/domains.go","lineNumber":563,"sourceCode":"\t}\n\tdefer dk.Close()\n\n\t// Generate new keys if they don't exist\n\tif !public.FileExists(dkimPriPath) || !public.FileExists(dkimPubPath) {\n\t\tmutex.Lock()\n\t\tdefer mutex.Unlock()\n\n\t\tvar res *v2.ExecResult\n\t\tres, 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\")\n\t\tif err != nil {\n\t\t\terr = fmt.Errorf(\"Failed to generate DKIM key pair: %v\", err)\n\t\t\treturn\n\t\t}\n\n\t\tif res != nil {\n\t\t\t_, err = public.WriteFile(dkimPubPath, res.Output)\n\t\t\tif err != nil {\n\t\t\t\terr = fmt.Errorf(\"Failed to write DKIM public key: %v\", err)\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\t// update dkim private key file permission to 0644\n\t\terr = os.Chmod(dkimPriPath, 0644)\n\t\tif err != nil {\n\t\t\terr = fmt.Errorf(\"Failed to change DKIM private key permissions: %v\", err)\n\t\t\treturn\n\t\t}\n\n\t\t// Skip DKIM signing config for relay-mapped domains — relay provider signs\n\t\trelayDomains, relayErr := GetRelayDomains(context.Background())\n\t\tif relayErr != nil {\n\t\t\tg.Log().Warning(context.Background(), \"Failed to check relay domains for DKIM signing:\", relayErr)\n\t\t\trelayDomains = make(map[string]bool)\n\t\t}\n","sourceCodeStart":545,"sourceCodeEnd":581,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/domains/domains.go#L545-L581","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","solutions":["Ensure the DKIM directory exists on the host (os.MkdirAll(dkimPath, 0755) before writing) and check the wrapped permission/disk error","Verify rspamadm output was non-empty; re-run key generation if res.Output is empty","Fix ownership/permissions on the dkim volume mount","Re-run GetDKIMRecord to regenerate both keys if the pub file is corrupt"],"exampleFix":"// before\nif res != nil {\n    _, err = public.WriteFile(dkimPubPath, res.Output)\n    if err != nil { err = fmt.Errorf(\"Failed to write DKIM public key: %v\", err); return }\n}\n// after\nif res == nil || len(strings.TrimSpace(res.Output)) == 0 {\n    err = fmt.Errorf(\"rspamadm dkim_keygen produced no output\")\n    return\n}\nif err = os.MkdirAll(dkimPath, 0755); err != nil { return }\nif _, err = public.WriteFile(dkimPubPath, res.Output); err != nil {\n    err = fmt.Errorf(\"Failed to write DKIM public key to %s: %v\", dkimPubPath, err)\n    return\n}","handlingStrategy":"validation","validationCode":"if err := os.MkdirAll(dkimPath, 0755); err != nil { return fmt.Errorf(\"cannot create dkim dir: %v\", err) }\nif err := unix.Access(dkimPath, unix.W_OK); err != nil { return fmt.Errorf(\"dkim dir not writable: %v\", err) }","typeGuard":null,"tryCatchPattern":"if _, err := public.WriteFile(dkimPubPath, res.Output); err != nil {\n    return fmt.Errorf(\"Failed to write DKIM public key %s: %v\", dkimPubPath, err) // includes path context\n}","preventionTips":["Create the DKIM directory before keygen, not after","Match volume ownership between rspamd container and host process","Check free disk space before key generation","Validate keygen output is non-empty before writing"],"tags":["filesystem","dkim","write-failed","rspamd"],"backgroundTag":"file-write-failed","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}