Billionmail/BillionMail · error

failed to restart postfix container: %v

Error message

failed to restart postfix container: %v

What it means

After patching /postfix.sh, Add restarts the Postfix container so the new BILLIONMAIL_HOSTNAME takes effect. This error wraps failure of RestartContainerByName. The hostname change was persisted but the running MTA still uses the old hostname until restart succeeds.

Source

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

		if hostname == "" || hostname == "mail.example.com" {
			err = public.SetDockerEnv("BILLIONMAIL_HOSTNAME", public.FormatMX(domain.Domain))

			if err != nil {
				return fmt.Errorf("failed to update BILLIONMAIL_HOSTNAME in .env file: %v", err)
			}

			// update postfix environment parameter
			_, err = public.DockerApiFromCtx(ctx).ExecCommandByName(ctx, consts.SERVICES.Postfix, []string{"bash", "-c", fmt.Sprintf("sed -i '/^BILLIONMAIL_HOSTNAME=/d' /postfix.sh && sed -i '/^#!\\/bin\\/bash/a BILLIONMAIL_HOSTNAME=%s' /postfix.sh", public.FormatMX(domain.Domain))}, "root")

			if err != nil {
				return fmt.Errorf("failed to update BILLIONMAIL_HOSTNAME in postfix container: %v", err)
			}

			// restart postfix service
			err = public.DockerApiFromCtx(ctx).RestartContainerByName(ctx, consts.SERVICES.Postfix)

			if err != nil {
				return fmt.Errorf("failed to restart postfix container: %v", err)
			}
		}

		// catchall
		if domain.Catchall != "" {
			err = setCatchall(ctx, domain.Domain, domain.Catchall)
		}
		return err
	}

	return err
}

func Update(ctx context.Context, updateData map[string]interface{}) error {

	domainName, _ := updateData["domain"].(string)

	_, err := g.DB().Model("domain").

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Check Docker daemon health and container state: docker ps -a, docker logs <postfix>
  2. Manually restart the postfix container (docker restart or docker compose restart postfix) to apply the hostname
  3. Verify dependent containers are healthy so compose allows the restart
  4. Retry AddDomain — the .env and postfix.sh edits already succeeded, so only the restart is pending

Example fix

// before
err = public.DockerApiFromCtx(ctx).RestartContainerByName(ctx, consts.SERVICES.Postfix)
if err != nil { return fmt.Errorf("failed to restart postfix container: %v", err) }
// after
if err := public.DockerApiFromCtx(ctx).RestartContainerByName(ctx, consts.SERVICES.Postfix); err != nil {
    logger.Warnf(ctx, "postfix restart failed (%v); config updated, restart manually", err)
    return fmt.Errorf("failed to restart postfix container: %v", err)
}
// verify afterwards
if err := public.DockerApiFromCtx(ctx).WaitContainerRunning(ctx, consts.SERVICES.Postfix, 30*time.Second); err != nil { ... }
Defensive patterns

Strategy: retry

Validate before calling

state, err := public.DockerApiFromCtx(ctx).InspectContainer(ctx, consts.SERVICES.Postfix)
if err != nil || state.State != "running" { return errors.New("cannot restart: postfix not running") }

Try / catch

err := retry.Do(3, 5*time.Second, func() error {
    return public.DockerApiFromCtx(ctx).RestartContainerByName(ctx, consts.SERVICES.Postfix)
})
if err != nil { return fmt.Errorf("failed to restart postfix container after 3 attempts: %v", err) }
// then wait for health before returning success

Prevention

When it happens

Trigger: AddDomain on the first/default-hostname domain when RestartContainerByName(ctx, consts.SERVICES.Postfix) fails — container stopped, Docker daemon unavailable, or restart timeout / dependency container refusing to stop.

Common situations: Docker daemon under load or restarting; container managed by compose with dependency ordering blocking restart; healthcheck failing so the container exits right after start; host resource exhaustion.

Related errors


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