Billionmail/BillionMail · error

failed to apply configurations, but rollback succeeded: %v

Error message

failed to apply configurations, but rollback succeeded: %v

What it means

ApplyConfigsWithRollback failed to apply the new configurations, but successfully restored the original files from backups. The system is back in its pre-apply state; the wrapped error explains why the apply failed. This is a 'safe failure' outcome and should be retried after fixing the underlying cause.

Source

Thrown at core/internal/service/multi_ip_domain/config_manager.go:72

// ApplyConfigsWithRollback Apply configurations and rollback on failure
func (m *ConfigManager) ApplyConfigsWithRollback(ctx context.Context, configs []map[string]interface{}) error {

	m.fileLocker.Lock()
	defer m.fileLocker.Unlock()

	backups, err := m.createBackups(ctx)
	if err != nil {
		return fmt.Errorf("failed to create backup: %v", err)
	}

	// Apply configurations
	if err := m.applyConfigs(ctx, configs); err != nil {

		g.Log().Debugf(ctx, "Failed to apply configurations, rolling back... Error: %v", err)
		if rollbackErr := m.rollback(ctx, backups); rollbackErr != nil {
			return fmt.Errorf("failed to apply configurations: %v, rollback also failed: %v", err, rollbackErr)
		}
		return fmt.Errorf("failed to apply configurations, but rollback succeeded: %v", err)
	}

	m.cleanupBackups(ctx, backups)
	return nil
}

// createBackups Create backups for Postfix's main.cf and master.cf
func (m *ConfigManager) createBackups(ctx context.Context) (map[string]string, error) {
	backups := make(map[string]string)

	files := []string{PostfixMainCfPath, PostfixMasterCfPath}

	for _, file := range files {
		if gfile.Exists(file) {
			content, err := ioutil.ReadFile(file)
			if err != nil {
				return nil, fmt.Errorf("failed to read file %s: %v", file, err)
			}

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Read the wrapped inner error (%v) to find why applyConfigs failed and fix that input/config
  2. Validate config inputs (IPs, domains, hostnames) before calling ApplyConfigsWithRollback
  3. Re-run the operation once the root cause is fixed — state was cleanly rolled back so it is safe to retry
  4. Check logs around 'Failed to apply configurations, rolling back...' for the apply error detail
Defensive patterns

Strategy: retry

Validate before calling

if err := validateConfigs(configs); err != nil { // check IPs, domains, hostnames
    return err
}
for _, f := range []string{PostfixMainCfPath, PostfixMasterCfPath} {
    if err := writableFile(f); err != nil { return err }
}

Try / catch

err := manager.ApplyConfigsWithRollback(ctx, configs)
if err != nil && strings.Contains(err.Error(), "but rollback succeeded") {
    // safe to retry after fixing cause
    log.Warnf("apply failed, rolled back cleanly: %v", err)
    fixCause(err) // e.g. correct invalid config input
    err = manager.ApplyConfigsWithRollback(ctx, configs)
}

Prevention

When it happens

Trigger: m.applyConfigs(ctx, configs) returned an error — e.g. writing a rendered postconf/main.cf failed, template rendering failed, or a validation step inside applyConfigs rejected the config — and m.rollback(ctx, backups) completed without error.

Common situations: Invalid config content generated for a domain/IP mapping; permission or disk errors during config write; hostname/IP validation failing for the supplied inputs; interrupted network mounts during apply.

Related errors


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