{"record":{"id":"b810ed938aeb0f95","repo":"caddyserver/caddy","slug":"v-additionally-aborting-app-s-v","errorCode":null,"errorMessage":"%v; additionally, aborting app %s: %v","messagePattern":"(.+?); additionally, aborting app (.+?): (.+?)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"caddy.go","lineNumber":454,"sourceCode":"\n\t\t\tif currentCtx.cfg != nil {\n\t\t\t\tcertmagic.Default.Storage = currentCtx.cfg.storage\n\t\t\t}\n\t\t}\n\t}()\n\n\t// Start\n\terr = func() error {\n\t\tstarted := make([]string, 0, len(ctx.cfg.apps))\n\t\tfor name, a := range ctx.cfg.apps {\n\t\t\terr := a.Start()\n\t\t\tif err != nil {\n\t\t\t\t// an app failed to start, so we need to stop\n\t\t\t\t// all other apps that were already started\n\t\t\t\tfor _, otherAppName := range started {\n\t\t\t\t\terr2 := ctx.cfg.apps[otherAppName].Stop()\n\t\t\t\t\tif err2 != nil {\n\t\t\t\t\t\terr = fmt.Errorf(\"%v; additionally, aborting app %s: %v\",\n\t\t\t\t\t\t\terr, otherAppName, err2)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn fmt.Errorf(\"%s app module: start: %v\", name, err)\n\t\t\t}\n\t\t\tstarted = append(started, name)\n\t\t}\n\t\treturn nil\n\t}()\n\tif err != nil {\n\t\treturn ctx, err\n\t}\n\tglobalMetrics.configSuccess.Set(1)\n\tglobalMetrics.configSuccessTime.SetToCurrentTime()\n\n\t// TODO: This event is experimental and subject to change.\n\tctx.emitEvent(\"started\", nil)\n","sourceCodeStart":436,"sourceCodeEnd":472,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/caddy.go#L436-L472","documentation":"During run(), if an app's Start() fails, Caddy stops every app that had already started to unwind cleanly. If stopping one of those already-started apps also fails, the stop error is chained onto the start error as '%v; additionally, aborting app %s: %v'. The primary error remains the app start failure; the secondary error only reports degraded shutdown, not the root cause.","triggerScenarios":"A multi-app config (e.g. http + tls + pk + custom apps) where a later app fails Start() and an earlier app's Stop() then errors — e.g. an http app that cannot release listeners, or a plugin whose Stop has bugs. Map iteration order makes 'later' nondeterministic across apps.","commonSituations":"One app failing to bind its resources (port in use, bad socket) while another app's shutdown path is broken (plugin bug, context already cancelled); custom plugins with poorly implemented Stop(); rarely, TLS storage lock contention during unwind.","solutions":["Fix the FIRST error — it names the app whose Start() failed; the 'additionally' clause is cleanup fallout.","Address the second error only if it persists after the first is fixed (usually a plugin Stop() bug).","Free conflicting ports/sockets, then retry; if shutdown left resources held, restart the process.","For plugin authors: make Stop() idempotent and non-blocking on cancelled contexts."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"ctx, err := caddy.Run(cfg)\nif err != nil && strings.Contains(err.Error(), \"additionally, aborting app\") {\n    // start failure + dirty unwind: restart process for clean state\n    log.Fatalf(\"app start failed and unwind errored: %v\", err)\n}","preventionTips":["Fix primary Start() errors first; the 'additionally' clause is fallout.","Plugin authors: implement Stop() idempotently and tolerate cancelled contexts.","Ensure app resource conflicts (ports, sockets) are resolved before start."],"tags":["caddy","apps","lifecycle","shutdown","compound-error"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}