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
- 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.
- For 3010, special-case it as success-with-reboot instead of letting it fall through to this throw.
- 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
- Special-case 3010 as success-with-reboot instead of a generic failure.
- For 1603, capture an MSI verbose log (/l*v) to find the failing action.
- Decode unknown codes against the installer type's documentation before reporting.
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
- Uninstaller timed out
- The system cannot find the file specified. Indicates that th
- The system cannot find the path specified. Indicates that th
- Access is denied. Indicates that user has no access right to
- Program is not recognized as an internal or external command
AI-assisted analysis of BCUninstaller/Bulk-Crap-Uninstaller@608321de98 (2026-08-13).
Data as JSON: /api/errors/a7dd73e9f1a55dfc.
Report an issue: GitHub.