Home: dotnet restore fails with NU1108 error ("Cycle detected") if csproj has the same name as a dependant PackageReference

Created on 29 Mar 2018  路  12Comments  路  Source: NuGet/Home

A real case - you want to play with a library, let's take Autofac. You create a folder named "autofac" then run dotnet new console then dotnet add package Autofac and then run VSCode anticipating a fun.
Agree to install required assets for .net project and run restore to get intellisense.
Bump! Error - NU1108: Cycle detected.

D:\Work\Learn\autofac>dotnet restore
  Restoring packages for D:\Work\Learn\autofac\autofac.csproj...
D:\Work\Learn\autofac\autofac.csproj : error NU1108: Cycle detected.
D:\Work\Learn\autofac\autofac.csproj : error NU1108:   autofac -> Autofac (>= 1.0.0).
  Generating MSBuild file D:\Work\Learn\autofac\obj\autofac.csproj.nuget.g.props.
  Restore failed in 247,83 ms for D:\Work\Learn\autofac\autofac.csproj.

then you have to renam autofac.csproj to autofac-sandbox.csproj and restore starts working but not VSCode. you'll have to recreate project. it pains.

D:\Work\Learn\autofac>dotnet restore
  Restoring packages for D:\Work\Learn\autofac\autofac-sandbox.csproj...
  Installing Autofac 2.2.4.900.
D:\Work\Learn\autofac\autofac-sandbox.csproj : warning NU1603: autofac-sandbox depends on Autofac (>= 1.0.0) but Autofac 1.0.0 was not found. An approximate best match of Autofac 2.2.4.900 was resolved.
Restore Backlog 3 PackageReference DCR

Most helpful comment

This is by design.

Since project.json, NuGet has been moving towards project-package duality.

A project and a dependency cannot have the same name.

I don't think NuGet needs to do anything different here.

All 12 comments

This is by design.

Since project.json, NuGet has been moving towards project-package duality.

A project and a dependency cannot have the same name.

I don't think NuGet needs to do anything different here.

Another case is if you have an analyzer library and want to use the published analyzer on the analyzer code.
I tried <NoWarn>NU1108</NoWarn> but it had no effect.

This is a general problem for toolset packages (DevelopmentDependency=true) that use previous versions of themselves during build. For example a Microsoft.SourceLink package.

I don't think NuGet needs to do anything different here.

I think NuGet needs to have a concept that allows it to distinguish between packages that are used in build and packages that are being built.

A workaround is to define PackageId to some unique value and then redefine it to the actual value in a target that runs just before Pack target.

  <PropertyGroup>
    <PackageId>*$(MSBuildProjectFullPath)*</PackageId>
  </PropertyGroup>

  <Target Name="_UpdatePackageId" BeforeTargets="$(PackDependsOn)" >
    <PropertyGroup>
      <PackageId>$(MSBuildProjectName)</PackageId>
    </PropertyGroup>
  </Target>

I think NuGet needs to have a concept that allows it to distinguish between packages that are used in build and packages that are being built.

I agree with this, it's just that other design decisions such as Dev dependency itself kind of limit/kill some of the options.
It'd be a significant undertaking, which we'd need to prioritize first.
// cc @rrelyea

Any progress on this issue? I ran into the same problem with a build package that is used by the project that builds the package.

I just hit this and I think it's a problem that needs addressing.

There are two ways to interpret a name when a project has the same name as a package. One of them results in a cycle, the other doesn't. How about trying both combinations and only failing when no self-consistent combinations are possible?

It is really unexpected honestly to try to interpret the name inside PackageReference as a project first. Shouldn't it try to interpret it as a package first, and only when that fails, fall back to projects?

And what does it even mean to have a PackageReference to a project? Shouldn't it then include a path to the .csproj and not just a name?

This is very strange and counter-intuitive design honestly.

@KirillOsenkov
I use the approach of @tmat as a workaround and put it into the Directory.Build.targets of my repository. It could also be moved into a build package:

  <!--Begin: Avoid cycle error when package builds itself-->
  <Choose>
    <When Condition="$(AvoidCycleErrorOnSelfReference) == 'true'">
      <PropertyGroup>
        <PackageId Condition="'$(PackageId)' == ''">$(MSBuildProjectName)</PackageId>
        <PackageIdTemp>$(PackageId)</PackageIdTemp>
        <PackageId>$(PackageId)_temp</PackageId>
      </PropertyGroup>
    </When>
  </Choose>
  <Target Name="_UpdatePackageId" BeforeTargets="$(PackDependsOn)" Condition="$(AvoidCycleErrorOnSelfReference) == 'true'" >
    <PropertyGroup>
      <PackageId>$(PackageIdTemp)</PackageId>
    </PropertyGroup>
  </Target>
  <!--End: Avoid cycle error when package builds itself-->

In a project where you run into the issue simply add:

    <PropertyGroup>
      <AvoidCycleErrorOnSelfReference>true</AvoidCycleErrorOnSelfReference>
    </PropertyGroup>

Came across this today. Created my standalone (not a package) csproj called "Validation" several months ago. Today I tried to include "PInvoke.User32" - this has a dependency on a package called "Validation". How am I, as a developer, supposed to know that I should not have used "Validation" for my project name.

@KirillOsenkov @tmat I tried the workaround mentioned earlier and it seems to have worked. BUT I'm not building a package so why should defining a PackageId change anything for me?

Just ran into this problem. Hacked around it by renaming the project directory. At the very least, a useful error message would be appreciated.

just discovered that the workaround from here https://github.com/NuGet/Home/issues/6754#issuecomment-592283619 just works as long as your development package has no other development package as dependency, for which you have to avoid the cyclic dependency error as well.
If a dev package has a dependency on another dev package for which you workaround the cycle detection error you'd get the '_temp' package id as the dependency name in the referencing package.

Does anyone have a workaround for that scenario?

@nkolev92
Would it be difficult to add a flag that allows us to suppress the error? In case of dev package the error is a false positive, because if you add the dev package with 'PrivateAssets='all'' configured, it doesn't become a dependency of itself -> no cyclic dependency in that scenario

Was this page helpful?
0 / 5 - 0 ratings