This project is read-only.
1

Closed

Update-Package fails with '<PkgName> was not installed in any project. Update failed.'

description

Applies to:
Package Manager Console Host Version 1.4.20701.9038 (Package Manager GUI is affected too)
Summary:
When trying to update a package (that has been installed for some project) if packages folder of consuming app has also a subfolder for the same package w/ smaller version number than the one that is referenced by consuming project, the update fails w/ message:
'<PkgName> was not installed in any project. Update failed.'
How to reproduce:
Just use any project that has a package reference. Go to \packages folder and make a copy of folder w/ currently used version for some package but name it so that new folder name has smaller version. E.g. if your app has a reference to log4net.1.2.10, copy log4net.1.2.10 to log4net.1.2.9 or any other smaller version. Go to VS and do update-package (or use GUI) to update log4net to let's say v.1.2.11.
Or (alternative way to reproduce) just unpack the attached solution to let's say "C:\foldername", open the solution in VS and register new local NuGet source w/ path C:\foldername\NuGetBug_PackageNotInstalled\BuildSupport\NuGet\Packages. Then select that source in PM console and execute
get-package -updates | update-package
Expected result: package is updated to newer version.
Actual result: Update fails w/ '<PkgName> was not installed in any project. Update failed.'
More details:
Digging in NuGet code w/ reflector leads to method called
private IPackage FindLocalPackage(string packageId, out bool appliesToProject);
Declaring Type: NuGet.VisualStudio.VsPackageManager
Assembly: NuGet.VisualStudio, Version=1.4.20701.9038

private IPackage FindLocalPackage(string packageId, out bool appliesToProject)
{
List<IPackage> source = base.LocalRepository.FindPackagesById(packageId).ToList<IPackage>();
if (!source.Any<IPackage>())
{
    throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, VsResources.UnknownPackage, new object[] { packageId }));
}
IPackage package = source.FirstOrDefault<IPackage>();
appliesToProject = this.IsProjectLevel(package);
if (!appliesToProject)
{
    if (source.Count > 1)
    {
        IProjectManager projectManager = null;
        IList<IPackage> packages = source;
        throw this.CreateAmbiguousUpdateException(projectManager, packages);
    }
    return package;
}
if (!this._sharedRepository.IsReferenced(package.Id, package.Version))
{
    throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, VsResources.PackageNotInstalledInAnyProject, new object[] { packageId }));
}
return package;
}

This implementation enumerates all versions installed but then checks only the first version if it's referenced by .csproj files (see source.FirstOrDefault above). It should check the version being uninstalled instead.

Thanks.

file attachments

Closed Oct 11, 2011 at 10:17 PM by JeffHandley
We don't know what steps led to this bad state and we haven't heard back for a couple of months.

comments

dotnetjunky wrote Jul 20, 2011 at 5:12 AM

Can you upload another file with normal Zip file? We don't have 7z installed.

GloomyOne wrote Jul 20, 2011 at 3:15 PM

Uploaded .zip

GloomyOne wrote Jul 22, 2011 at 3:16 PM

Any updates? Do you need any other information?

dfowler wrote Aug 4, 2011 at 8:02 AM

How did you end up in this situation in the first place? Are those packages left over in the packages folder because they weren't cleaned up correctly? Also, have you tried specifying the version with Update-Package?

GloomyOne wrote Aug 4, 2011 at 11:15 PM

Exactly. Update-package fails to remove old package w/ 'Directory not empty'.
Also, we have let's say 'class library project' and 'web app project'. Both are updated often and (unfortunately) we decided to use packages as a means to deliver 'class library' to 'web app'.
So very popular scenario is:
  1. Developer A check out both project from SVN (let's say WebApp is using ClassLibrary v.1.0 at the moment).
  2. Developer A implements a new feature in 'class library', builds new class library package, updates class library in web app to test the feature. Update-package may leave old folder in web app.
  3. After testing, developer A tries to commit changes to both projects to SVN. Commit fails because developer B has committed new revision to both projects.
    Developer A does svn-update on both projects. He either gets conflicts in WebApp.csproj and packages.config (because WebApp.csproj was modified by nuget when developer B did update-package) or even worse, SVN client merges changes and WebApp.csproj and/or WebApp\packages.config now have two references to different versions of ClassLibrary package. Also, WebApp\packages has now more than one folder for ClassLibrary package (one was checked in by developer B, one was restored by svn-update, one was created by developer A). If developer A doesn't remove everything except the folder with latest version, the update-package ClassLibrary will fail.
    We wanted tighter control over which version of ClassLibrary is used by WebApp, but so far Nuget proved completely usable for our purposes. Nuget adds just too much hassle (along w/ this bug and the bug preventing nuget from deleting old package on update-package and other dependency graph resolution bugs I haven't entered yet). Sorry if I sound disappointed but I uploaded exact repro project and even debugged it down to the exact failing line of code. Is this enough to fix it? In similar situation NHibernate team fixed the bug on the same day.
    Thanks.

dfowler wrote Aug 5, 2011 at 9:13 AM

The issue here is I'm convinced the problem isn't the line of code you point out but the scenario you're trying to accomplish and the stumbles you face getting there. You mentioned that you during a merge packages.config ends up in a bad state (i.e duplicate entries etc). The repro project isn't as useful as knowing how you got into that state in the first place. You mention that "Update-package fails to remove old package w/ 'Directory not empty'. ", I've seen this also, but it does remove the package file since that is never in the way, but it may fail to clean up the directory which doesn't make a difference to nuget since it only knows about package files not folders.

I notice you ran Get-Package -Updates | Update-Package.

Have you tried just running Update-Package? There's a huge difference with those commands (since update-package tries to figure out the best order to update packages vs the above script).

grahamrhay wrote Mar 14, 2012 at 12:58 PM

I managed to get into this situation by updating a package, and then reverting the changes to packages.config & the csproj file. We ignore the contents of the /packages folder (and use package restore), so the new package didn't get removed.

Clearing out the packages folder fixed the problem, but a better error message would be nice :)