{"record":{"id":"5af198e56b6a5de0","repo":"Billionmail/BillionMail","slug":"failed-to-restart-postfix-container-v","errorCode":null,"errorMessage":"failed to restart postfix container: %v","messagePattern":"failed to restart postfix container: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/domains/domains.go","lineNumber":133,"sourceCode":"\t\tif hostname == \"\" || hostname == \"mail.example.com\" {\n\t\t\terr = public.SetDockerEnv(\"BILLIONMAIL_HOSTNAME\", public.FormatMX(domain.Domain))\n\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to update BILLIONMAIL_HOSTNAME in .env file: %v\", err)\n\t\t\t}\n\n\t\t\t// update postfix environment parameter\n\t\t\t_, 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\")\n\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to update BILLIONMAIL_HOSTNAME in postfix container: %v\", err)\n\t\t\t}\n\n\t\t\t// restart postfix service\n\t\t\terr = public.DockerApiFromCtx(ctx).RestartContainerByName(ctx, consts.SERVICES.Postfix)\n\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to restart postfix container: %v\", err)\n\t\t\t}\n\t\t}\n\n\t\t// catchall\n\t\tif domain.Catchall != \"\" {\n\t\t\terr = setCatchall(ctx, domain.Domain, domain.Catchall)\n\t\t}\n\t\treturn err\n\t}\n\n\treturn err\n}\n\nfunc Update(ctx context.Context, updateData map[string]interface{}) error {\n\n\tdomainName, _ := updateData[\"domain\"].(string)\n\n\t_, err := g.DB().Model(\"domain\").","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/domains/domains.go#L115-L151","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check Docker daemon health and container state: docker ps -a, docker logs <postfix>","Manually restart the postfix container (docker restart or docker compose restart postfix) to apply the hostname","Verify dependent containers are healthy so compose allows the restart","Retry AddDomain — the .env and postfix.sh edits already succeeded, so only the restart is pending"],"exampleFix":"// before\nerr = public.DockerApiFromCtx(ctx).RestartContainerByName(ctx, consts.SERVICES.Postfix)\nif err != nil { return fmt.Errorf(\"failed to restart postfix container: %v\", err) }\n// after\nif err := public.DockerApiFromCtx(ctx).RestartContainerByName(ctx, consts.SERVICES.Postfix); err != nil {\n    logger.Warnf(ctx, \"postfix restart failed (%v); config updated, restart manually\", err)\n    return fmt.Errorf(\"failed to restart postfix container: %v\", err)\n}\n// verify afterwards\nif err := public.DockerApiFromCtx(ctx).WaitContainerRunning(ctx, consts.SERVICES.Postfix, 30*time.Second); err != nil { ... }","handlingStrategy":"retry","validationCode":"state, err := public.DockerApiFromCtx(ctx).InspectContainer(ctx, consts.SERVICES.Postfix)\nif err != nil || state.State != \"running\" { return errors.New(\"cannot restart: postfix not running\") }","typeGuard":null,"tryCatchPattern":"err := retry.Do(3, 5*time.Second, func() error {\n    return public.DockerApiFromCtx(ctx).RestartContainerByName(ctx, consts.SERVICES.Postfix)\n})\nif err != nil { return fmt.Errorf(\"failed to restart postfix container after 3 attempts: %v\", err) }\n// then wait for health before returning success","preventionTips":["Add a post-restart healthcheck wait before reporting success","Ensure docker daemon has restart budget (timeouts) during bulk domain provisioning","Monitor docker events for container die/restart loops","Keep compose dependency ordering correct so postfix can restart independently"],"tags":["docker","postfix","container-restart"],"backgroundTag":"container-restart-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"}