BCUninstaller/Bulk-Crap-Uninstaller · error · IOException

Uninstaller returned error code: {exitVar}

Error message

Uninstaller returned error code: {exitVar}

What it means

The default case of the exit-code switch: exitVar did not match any of the known codes (2/3/5/9009/-2147024846) and is not a CTRL+C termination, so the code throws IOException with Localisation.UninstallError_UninstallerReturnedCode + exitVar. This is the generic 'uninstaller ran but reported a non-success, non-classified exit code' failure.

Source

Thrown at source/UninstallTools/Uninstaller/BulkUninstallEntry.cs:450

                            else
                            {
                                switch (exitVar)
                                {
                                    case 2:
                                        throw new Exception("The system cannot find the file specified. Indicates that the file can not be found in specified location.");
                                    case 3:
                                        throw new Exception("The system cannot find the path specified. Indicates that the specified path can not be found.");
                                    case 5:
                                        throw new Exception("Access is denied. Indicates that user has no access right to specified resource.");
                                    case 9009:
                                        throw new Exception("Program is not recognized as an internal or external command, operable program or batch file.");
                                    case -2147024846:
                                        throw new Exception("0x80070032 - This app is part of Windows and cannot be uninstalled on a per-user basis.");

                                    default:
                                        if (options.RetryFailedQuiet || (UninstallerEntry.UninstallerKind == UninstallerType.Nsis && !options.PreferQuiet))
                                            retry = true;
                                        throw new IOException(Localisation.UninstallError_UninstallerReturnedCode + exitVar);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                error = ex;
                Trace.WriteLine(@$"Exception when uninstalling {UninstallerEntry.DisplayName}: {ex}");
            }
            finally
            {
                try
                {
                    _perfCounterBuffer.ForEach(x => x.Value.Dispose());
                }
                catch

View on GitHub (pinned to 608321de98)

Solutions

  1. Decode the numeric code: 1603 = fatal error (often locked files), 3010 = success-but-reboot (should be treated as success with a reboot prompt), consult the installer type's docs.
  2. For 3010, special-case it as success-with-reboot instead of letting it fall through to this throw.
  3. Run the same uninstaller with verbose logging (/qn /l*v for MSI) to capture why it returned a non-zero code.

Example fix

// before
// (library default case throws IOException with exitVar)

// caller side: decode known codes before reporting
try { manager.RunUninstaller(entry, options); }
catch (IOException ex) when (exitVar == 3010)
{
    entry.MarkSuccessRequiresReboot();
}
catch (IOException ex) when (exitVar == 1603)
{
    entry.MarkFailed("MSI fatal error — close the app and retry.");
}
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

null

Try / catch

try { manager.RunUninstaller(entry, options); }
catch (IOException ex)
{
    var code = ExtractExitCode(ex.Message);
    if (code == 3010) entry.MarkSuccessRequiresReboot();
    else if (code == 1603) entry.MarkFailed("MSI fatal error; close the app and retry.");
    else throw;
}

Prevention

When it happens

Trigger: The uninstaller process completed and returned an exit code the harness does not specifically decode — e.g. 1603 (MSI install/uninstall fatal error), 3010 (success-requires-reboot treated as error here), or any vendor-specific non-zero code.

Common situations: MSI uninstaller returns 1603 because a file was in use; NSIS installer returns its custom error code; a 'success but reboot required' (3010) lands here and is reported as a plain failure.

Related errors


AI-assisted analysis of BCUninstaller/Bulk-Crap-Uninstaller@608321de98 (2026-08-13). Data as JSON: /api/errors/a7dd73e9f1a55dfc. Report an issue: GitHub.