{"record":{"id":"da234fe56bac7620","repo":"dotnet/runtime","slug":"coreclr-shutdown-2-failed-error-0x-08x","errorCode":null,"errorMessage":"coreclr_shutdown_2 failed - Error: 0x%08x\n","messagePattern":"coreclr_shutdown_2 failed - Error: 0x%08x\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/coreclr/hosts/corerun/corerun.cpp","lineNumber":689,"sourceCode":"    }\n#endif // TARGET_WASI\n    return final_exit_code;\n#endif // TARGET_BROWSER\n}\n\nextern \"C\" int corerun_shutdown(int exit_code)\n{\n    coreclr_shutdown_2_ptr coreclr_shutdown2_func = nullptr;\n    if (!try_get_export(coreclr_mod, \"coreclr_shutdown_2\", (void**)&coreclr_shutdown2_func))\n    {\n        return -1;\n    }\n\n    int latched_exit_code = 0;\n    int result = coreclr_shutdown2_func(CurrentClrInstance, CurrentAppDomainId, &latched_exit_code);\n    if (FAILED(result))\n    {\n        pal::fprintf(stderr, W(\"coreclr_shutdown_2 failed - Error: 0x%08x\\n\"), result);\n        exit_code = -1;\n    }\n\n    if (exit_code != -1)\n        exit_code = latched_exit_code;\n\n    ::free((void*)s_core_libs_path);\n    ::free((void*)s_core_root_path);\n    return exit_code;\n}\n\n// Display the command line options\nstatic void display_usage()\n{\n    pal::fprintf(\n        stderr,\n        W(\"USAGE: corerun [OPTIONS] assembly [ARGUMENTS]\\n\")\n        W(\"\\n\")","sourceCodeStart":671,"sourceCodeEnd":707,"githubUrl":"https://github.com/dotnet/runtime/blob/290d5ab72cc1102813fbc0406fb186ceadabc340/src/coreclr/hosts/corerun/corerun.cpp#L671-L707","documentation":"Printed in corerun_shutdown() when coreclr_shutdown_2() returns a failing HRESULT. The managed Main already executed and produced an exit code; this is a best-effort shutdown failure. The host forces exit_code = -1 so the process reports failure even if Main returned success.","triggerScenarios":"coreclr_shutdown2_func(CurrentClrInstance, CurrentAppDomainId, &latched_exit_code) returns FAILED. Common when: shutdown is called on an already-torn-down runtime, a managed thread refused to stop, or a graceful shutdown timed out.","commonSituations":"Managed code left foreground threads running; native shutdown called twice; a pinned/unloadable assembly blocked teardown; runtime was only partially initialized due to an earlier recoverable error.","solutions":["Treat shutdown failure as non-fatal for the user's result but investigate lingering managed threads or background work in Main.","Ensure Main returns / awaits all tasks before exiting so no foreground threads block shutdown.","Avoid double-shutdown (calling corerun_shutdown twice) — the runtime tears down once.","If reproducible only under load, profile for threads that ignore cancellation."],"exampleFix":"// before: Main leaves a foreground thread running\nstatic void Main() { new Thread(() => while(true){}) { IsBackground=false }.Start(); }\n// after: mark background or exit cleanly\nstatic void Main() { using var cts = new CancellationTokenSource(); new Thread(Work){IsBackground=true}.Start(); cts.Cancel(); }","handlingStrategy":"validation","validationCode":"// managed-side: ensure Main awaits all work and no foreground threads linger\nstatic async Task Main()\n{\n    using var cts = new CancellationTokenSource();\n    var t = Task.Run(() => Worker(cts.Token));\n    cts.CancelAfter(TimeSpan.FromSeconds(30));\n    await t; // do not return until work is done\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Ensure Main awaits all outstanding tasks before returning.","Mark long-running worker threads as background (IsBackground=true).","Never call corerun_shutdown twice.","Treat a shutdown-2 failure as a symptom of incomplete cleanup, not the root cause."],"tags":["coreclr","corerun","runtime-host","shutdown","hresult"],"analyzedSha":"290d5ab72cc1102813fbc0406fb186ceadabc340","analyzedAt":"2026-08-06T19:57:01.276Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}