microsoft/aspire · error · ProjectUpdaterException
The project file was updated successfully, but the…
Error message
The project file was updated successfully, but the PackageVersion entry for '{packageId}' could not be removed from '{cpmInfo.DirectoryPackagesPropsFile.FullName}': {ex.Message}. Please manually remove the <PackageVersion Include="{packageId}" ... /> entry from this file to avoid NU1009 build errors. What it means
During CPM (Central Package Management) migration, the updater first updates the csproj to use Aspire.* package versions, then removes the corresponding <PackageVersion> entries from Directory.Packages.props. If that removal throws (file locked, save failure, parse error), the csproj is already modified and cannot be rolled back, so this exception tells the user the exact manual step left to avoid NU1009 (transitive Central Package Management) errors.
Solutions
- Manually remove the <PackageVersion Include="{packageId}" ... /> entry for the named package from Directory.Packages.props, then build to confirm no NU1009 error.
- Close editors/lockers or fix file permissions on Directory.Packages.props and re-run `aspire update`.
- If the file is malformed XML, repair or restore it before hand-editing the PackageVersion entry.
Example fix
// before (Directory.Packages.props) <PackageVersion Include="Aspire.Hosting.AppHost" Version="9.0.0" /> // after <!-- entry removed -->
Defensive patterns
Strategy: try-catch
Validate before calling
var propsPath = Path.Combine(repoRoot, "Directory.Packages.props");
if (File.Exists(propsPath))
{
using var stream = File.Open(propsPath, FileMode.Open, FileAccess.ReadWrite, FileShare.None); // throws if locked/read-only
var doc = new XmlDocument(); doc.Load(stream); // throws if malformed
} Try / catch
try { await updater.UpdateAsync(...); }
catch (ProjectUpdaterException ex) when (ex.Message.Contains("could not be removed"))
{
// follow the message: remove the named <PackageVersion> entry from Directory.Packages.props manually
} Prevention
- Close editors and builds that lock Directory.Packages.props before running `aspire update`.
- Keep Directory.Packages.props under source control so you can diff/repair after a partial migration.
- After any update, build once to catch NU1009 from leftover PackageVersion entries.
When it happens
Trigger: ProjectUpdater removing a PackageVersion entry from Directory.Packages.props after already saving the updated csproj, and the props-file write/parse fails — e.g. Directory.Packages.props is read-only, locked by another process, or malformed XML.
Common situations: Directory.Packages.props open in an editor or held by a build; insufficient write permissions on the props file; Directory.Packages.props with XML that fails to parse mid-migration.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- Could not find PackageVersion element for
- -32603
- ASPIRE_TERMINAL_HOST_INVOCATION_ARGS has unterminated
- Could not find root element in
- Could not find '#:sdk Aspire.AppHost.Sdk@
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/34f399cb5ef3df33.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Cli/Projects/ProjectUpdater.cs:859
return;
}
var parentNode = packageVersionNode.ParentNode;
RemoveNodeWithWhitespace(packageVersionNode);
if (parentNode.Name == "ItemGroup" && IsEmptyOrWhitespace(parentNode))
{
RemoveNodeWithWhitespace(parentNode);
}
propsDocument.Save(cpmInfo.DirectoryPackagesPropsFile.FullName);
}
catch (Exception ex)
{
// The csproj has already been updated at this point, so we can't roll back.
// Inform the user what manual step is needed to complete the migration.
throw new ProjectUpdaterException(
string.Format(
CultureInfo.InvariantCulture,
"The project file was updated successfully, but the PackageVersion entry for '{0}' could not be " +
"removed from '{1}': {2}. Please manually remove the <PackageVersion Include=\"{0}\" ... /> " +
"entry from this file to avoid NU1009 build errors.",
packageId,
cpmInfo.DirectoryPackagesPropsFile.FullName,
ex.Message),
ex);
}
}
private static async Task UpdateSdkVersionInSingleFileAppHostAsync(FileInfo projectFile, NuGetPackageCli package)
{
var fileContent = await File.ReadAllTextAsync(projectFile.FullName);
// Look for the #:sdk Aspire.AppHost.Sdk@<version> directive
var match = SdkDirectiveRegex().Match(fileContent);View on GitHub (pinned to 25830f84bd)