{"record":{"id":"ec34a21f91d06d4a","repo":"Billionmail/BillionMail","slug":"failed-to-create-backup-v","errorCode":null,"errorMessage":"failed to create backup: %v","messagePattern":"failed to create backup: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/multi_ip_domain/config_manager.go","lineNumber":62,"sourceCode":"func NewConfigManager(ctx context.Context) (*ConfigManager, error) {\n\tmanager := &ConfigManager{\n\t\tctx:             ctx,\n\t\tmasterCfEntries: []string{},\n\t\tfileLocker:      gmutex.New(),\n\t}\n\n\treturn manager, nil\n}\n\n// ApplyConfigsWithRollback Apply configurations and rollback on failure\nfunc (m *ConfigManager) ApplyConfigsWithRollback(ctx context.Context, configs []map[string]interface{}) error {\n\n\tm.fileLocker.Lock()\n\tdefer m.fileLocker.Unlock()\n\n\tbackups, err := m.createBackups(ctx)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create backup: %v\", err)\n\t}\n\n\t// Apply configurations\n\tif err := m.applyConfigs(ctx, configs); err != nil {\n\n\t\tg.Log().Debugf(ctx, \"Failed to apply configurations, rolling back... Error: %v\", err)\n\t\tif rollbackErr := m.rollback(ctx, backups); rollbackErr != nil {\n\t\t\treturn fmt.Errorf(\"failed to apply configurations: %v, rollback also failed: %v\", err, rollbackErr)\n\t\t}\n\t\treturn fmt.Errorf(\"failed to apply configurations, but rollback succeeded: %v\", err)\n\t}\n\n\tm.cleanupBackups(ctx, backups)\n\treturn nil\n}\n\n// createBackups Create backups for Postfix's main.cf and master.cf\nfunc (m *ConfigManager) createBackups(ctx context.Context) (map[string]string, error) {","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/multi_ip_domain/config_manager.go#L44-L80","documentation":"ApplyConfigsWithRollback wraps any failure from createBackups with 'failed to create backup'. Backups of postfix main.cf and master.cf are mandatory before applying new configs; if a backup can't be made the whole apply is aborted to guarantee rollback capability.","triggerScenarios":"ioutil.ReadFile fails on an existing PostfixMainCfPath/PostfixMasterCfPath (permissions, race-deleted file) or ioutil.WriteFile of the .backup.<nanotimestamp> file fails (disk full, read-only mount, permission denied on the config directory).","commonSituations":"Container running without root/file permissions on /etc/postfix; disk full on the host; configs mounted read-only in Docker; postfix config paths misconfigured to nonexistent locations; SELinux/AppArmor denying writes.","solutions":["Check filesystem permissions on the postfix config files and directory (process must read the files and write alongside them)","Free disk space — backup write failures are commonly ENOSPC","Verify PostfixMainCfPath/PostfixMasterCfPath point at real files and the mount is writable","Run the service with sufficient privileges or pre-grant write access to the config directory"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"for _, f := range []string{PostfixMainCfPath, PostfixMasterCfPath} {\n    if fi, err := os.Stat(f); err != nil || !fi.Mode().IsRegular() {\n        return fmt.Errorf(\"cannot back up %s: %v\", f, err)\n    }\n    if err := unix.Access(filepath.Dir(f), unix.W_OK); err != nil {\n        return fmt.Errorf(\"config dir not writable: %v\", err)\n    }\n}\nif free, _ := diskFree(\"/etc/postfix\"); free < 10*1024*1024 { return errors.New(\"low disk space\") }","typeGuard":null,"tryCatchPattern":"err := manager.ApplyConfigsWithRollback(ctx, configs)\nif err != nil && strings.HasPrefix(err.Error(), \"failed to create backup\") {\n    // environment problem: check permissions/disk, alert ops, do not retry blindly\n    alertOps(err)\n}","preventionTips":["Ensure the service runs with read access to postfix configs and write access to their directory","Monitor disk space where backups are written","Avoid read-only mounts for config directories","Pre-check that path constants match the deployment layout"],"tags":["filesystem","backup","postfix"],"backgroundTag":"backup-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"}