{"record":{"id":"2ea7274ad3c16339","repo":"Billionmail/BillionMail","slug":"failed-to-update-sni-map-v","errorCode":null,"errorMessage":"failed to update SNI map: %v","messagePattern":"failed to update SNI map: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/mail_service/certificate.go","lineNumber":306,"sourceCode":"\tif err := os.MkdirAll(domainDir, 0755); err != nil {\n\t\treturn fmt.Errorf(\"failed to create domain directory: %v\", err)\n\t}\n\n\tvmailCert := filepath.Join(domainDir, \"fullchain.pem\")\n\tvmailKey := filepath.Join(domainDir, \"privkey.pem\")\n\n\t// Write certificate and key to files\n\tif err := os.WriteFile(vmailCert, []byte(csrPem), 0755); err != nil {\n\t\treturn fmt.Errorf(\"failed to write certificate file: %v\", err)\n\t}\n\n\tif err := os.WriteFile(vmailKey, []byte(keyPem), 0755); err != nil {\n\t\treturn fmt.Errorf(\"failed to write key file: %v\", err)\n\t}\n\n\t// Create SNI mapping table\n\tif err := c.updatePostfixSNIMap(public.FormatMX(domain), vmailCert, vmailKey); err != nil {\n\t\treturn fmt.Errorf(\"failed to update SNI map: %v\", err)\n\t}\n\n\treturn nil\n}\n\n// updatePostfixSNIMap updates Postfix SNI mapping table\nfunc (c *Certificate) updatePostfixSNIMap(domain, certPath, keyPath string) error {\n\t// Read Postfix configuration file\n\tcontent, err := os.ReadFile(c.PostfixSNIPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read postfix config: %v\", err)\n\t}\n\n\t// Update SNI mapping table\n\tlines := strings.Split(string(content), \"\\n\")\n\taddNewLine := true\n\n\tfor i, line := range lines {","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/mail_service/certificate.go#L288-L324","documentation":"After writing the domain cert/key, updatePostfixVMailConfig calls updatePostfixSNIMap to register the domain (via public.FormatMX) in Postfix's vmail_ssl.map, and wraps any failure with this message. The SNI map is what lets Postfix select the right cert per hostname at TLS handshake.","triggerScenarios":"SetSNI or SetPostfixVMailCert completes file writes but updatePostfixSNIMap fails — typically because the SNI map file (c.PostfixSNIPath) cannot be read/written or the postmap exec in the Postfix container fails.","commonSituations":"vmail_ssl.map missing from the Postfix conf volume; map owned by root; Postfix container not running so postmap exec fails; path mismatch between host and container mounts.","solutions":["Verify the Postfix SNI map file exists and is writable (ls -l the path in c.PostfixSNIPath).","Ensure the Postfix container (consts.SERVICES.Postfix) is up so postmap can run.","Inspect the wrapped inner error — it distinguishes read/write failures from postmap exec failures.","Recreate vmail_ssl.map with correct ownership if it is missing or corrupt.","Retry SetSNI and confirm the MX-hostname entry appears in the map."],"exampleFix":"// before\nif err := c.updatePostfixSNIMap(public.FormatMX(domain), vmailCert, vmailKey); err != nil {\n    return fmt.Errorf(\"failed to update SNI map: %v\", err)\n}\n// after\nif err := c.updatePostfixSNIMap(public.FormatMX(domain), vmailCert, vmailKey); err != nil {\n    return fmt.Errorf(\"failed to update SNI map for %s: %w\", domain, err)\n}","handlingStrategy":"try-catch","validationCode":"// before calling SetSNI / SetPostfixVMailCert:\nif _, err := os.Stat(c.PostfixSNIPath); err != nil {\n    return fmt.Errorf(\"sni map missing at %s: %v\", c.PostfixSNIPath, err)\n}\nif !isContainerRunning(consts.SERVICES.Postfix) {\n    return fmt.Errorf(\"postfix container not running\")\n}","typeGuard":null,"tryCatchPattern":"err := svc.SetPostfixVMailCert(ctx, domain, cert, key)\nif err != nil && strings.Contains(err.Error(), \"failed to update SNI map\") {\n    log.Printf(\"SNI files written but map update failed — check vmail_ssl.map perms and postfix container: %v\", err)\n    // retry once after ensuring postfix is up\n}","preventionTips":["Health-check the Postfix container before cert operations.","Keep PostfixSNIPath constant in sync with the container volume layout.","Ensure vmail_ssl.map exists with writable ownership at install time.","Re-run postmap manually if the map was edited out-of-band."],"tags":["postfix","sni","ssl-certificate","configuration"],"backgroundTag":"postfix-sni-map-update-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"}