BCUninstaller/Bulk-Crap-Uninstaller · error · InvalidDataException
The uninstall list file could not be deserialized.
Error message
The uninstall list file could not be deserialized.
What it means
In Deserialize, after the root-element check passes, the code runs serializer.Deserialize(reader) as UninstallList and throws InvalidDataException if the result is null. A null result means the XmlSerializer returned null (which happens when the element existed but contained no deserialisable content, or the cast target mismatched), so the caller would otherwise get a NullReferenceException on result.Filters.
Source
Thrown at source/UninstallTools/Lists/UninstallList.cs:168
if (Filters.Contains(item))
Filters.Remove(item);
}
private static UninstallList Deserialize(XmlSerializer serializer, XmlReader reader)
{
using (reader)
{
reader.MoveToContent();
if (reader.NodeType != XmlNodeType.Element ||
!string.Equals(reader.LocalName, nameof(UninstallList), StringComparison.Ordinal))
{
throw new InvalidDataException(
$"The file does not contain an uninstall list. Expected root element '{nameof(UninstallList)}' but found '{reader.LocalName}'.");
}
var result = serializer.Deserialize(reader) as UninstallList;
if (result == null)
throw new InvalidDataException("The uninstall list file could not be deserialized.");
result.Filters ??= new List<Filter>();
return result;
}
}
private static InvalidDataException CreateInvalidDataException(Exception ex)
{
var xmlException = ex as XmlException ?? ex.InnerException as XmlException;
if (xmlException != null)
{
return new InvalidDataException(
$"The uninstall list XML is invalid at line {xmlException.LineNumber}, position {xmlException.LinePosition}: {xmlException.Message}",
ex);
}
return new InvalidDataException("The uninstall list file is not valid XML.", ex);
}View on GitHub (pinned to 608321de98)
Solutions
- Keep the UninstallList type name/namespace stable, or add an XmlType/XmlRoot alias matching the legacy name.
- On this exception, offer to open the file as text so the user can inspect/recover it.
- Add an XML schema (XSD) and validate before deserialising to surface corruption earlier.
Example fix
// before
var result = serializer.Deserialize(reader) as UninstallList;
// (library code) after — keep type identity stable:
[XmlRoot("UninstallList"), XmlType("UninstallList")]
public class UninstallList { /* ... */ }
// caller side: catch and recover
try { list = UninstallList.ReadFromFile(path); }
catch (InvalidDataException) { list = RestoreFromBackup(path); } Defensive patterns
Strategy: try-catch
Validate before calling
null
Type guard
null
Try / catch
try { list = UninstallList.ReadFromFile(path); }
catch (InvalidDataException ex) when (ex.Message.Contains("could not be deserialized"))
{
list = RestoreFromBackup(path) ?? new UninstallList();
} Prevention
- Keep the UninstallList type name and namespace stable between releases; add XmlRoot/XmlType aliases if renaming.
- Version-stamp list files and ship forward-migrators.
- Round-trip-test serialisation on every schema change.
When it happens
Trigger: The XML has a <UninstallList> root that passed the name check but Deserialize still returned null — e.g. xsi:nil="true" on the root, a serialisation attribute mismatch between the assembly that wrote and the one that reads, or a corrupted element that the serializer silently skips.
Common situations: Version skew: the UninstallList class was refactored (renamed/namespace-changed) and an old file's root matches the local name but the type no longer maps; partial/corrupt file that deserialises to nothing.
Related errors
- The file does not contain an uninstall list. Expected root e
- The uninstall list file is empty.
- List is empty
- Value cannot be null or empty
- Value cannot contain newlines
AI-assisted analysis of BCUninstaller/Bulk-Crap-Uninstaller@608321de98 (2026-08-13).
Data as JSON: /api/errors/ec949bf69e84a5a2.
Report an issue: GitHub.