abpframework/abp · error · ArgumentException
Cyclic dependency found! Item: {item}
Error message
Cyclic dependency found! Item: {item} What it means
Thrown by DefaultBuildProjectListSorter during a topological sort of .NET projects. The visited-map DFS detects that a project is still 'in process' (on the current recursion stack) when reached again, which is the textbook signature of a reference cycle. Build ordering cannot be produced until the cycle is broken.
Source
Thrown at framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/DefaultBuildProjectListSorter.cs:42
}
return sorted;
}
private void SortByDependenciesVisit(
List<DotNetProjectInfo> source,
DotNetProjectInfo item,
List<DotNetProjectInfo> sorted,
Dictionary<DotNetProjectInfo, bool> visited)
{
bool inProcess;
var alreadyVisited = visited.TryGetValue(item, out inProcess);
if (alreadyVisited)
{
if (inProcess)
{
throw new ArgumentException("Cyclic dependency found! Item: " + item);
}
}
else
{
visited[item] = true;
var dependencies = item.Dependencies;
if (dependencies != null)
{
foreach (var dependency in dependencies)
{
var dependencyItem = source.FirstOrDefault(e => e.CsProjPath == dependency.CsProjPath);
if (dependencyItem != null)
{
SortByDependenciesVisit(source, dependencyItem, sorted, visited);
}
}
}View on GitHub (pinned to 7ed43b1931)
Solutions
- Identify the cycle: the thrown item string and its Dependencies point to the loop; trace ProjectReference chains from the named .csproj back to itself.
- Break the cycle by removing the offending ProjectReference (use a shared interface/abstraction project instead of a back-reference).
- Run 'dotnet build' on the affected projects to confirm the cycle is also flagged by the SDK.
- Use a dependency-analysis tool (e.g., 'dotnet list package' or a project-reference graph viewer) to visualize and remove the loop.
Example fix
<!-- before: ProjectA.csproj references ProjectB, ProjectB references ProjectA --> <ProjectReference Include="..\ProjectB\ProjectB.csproj" /> <!-- after: extract shared code into a ProjectShared that both reference, with no back-edge --> <!-- ProjectA -> ProjectShared, ProjectB -> ProjectShared -->
Defensive patterns
Strategy: validation
Validate before calling
// Detect a project-reference cycle before invoking the sorter.
bool HasCycle(List<DotNetProjectInfo> projects)
{
var byPath = projects.ToDictionary(p => p.CsProjPath);
var visited = new HashSet<string>();
var stack = new HashSet<string>();
bool Dfs(string path)
{
if (stack.Contains(path)) return true;
if (!visited.Add(path)) return false;
stack.Add(path);
if (byPath.TryGetValue(path, out var p) && p.Dependencies != null)
foreach (var d in p.Dependencies)
if (byPath.ContainsKey(d.CsProjPath) && Dfs(d.CsProjPath)) return true;
stack.Remove(path);
return false;
}
return projects.Any(p => Dfs(p.CsProjPath));
}
if (HasCycle(projects)) throw new InvalidOperationException("Project reference cycle detected; remove the back-reference."); Type guard
// (uses validation code above; no type to guard)
Try / catch
try
{
var ordered = sorter.SortByDependencies(projects);
}
catch (ArgumentException ex) when (ex.Message.Contains("Cyclic dependency", StringComparison.Ordinal))
{
logger.LogError(ex, "Cycle detected while ordering projects; remove the offending ProjectReference.");
throw;
} Prevention
- Keep a shared abstractions project that downstream projects reference, avoiding back-edges.
- Run 'dotnet build' locally to catch cycles early.
- Review new ProjectReference additions for transitive cycles.
- Visualize project references periodically in large solutions.
When it happens
Trigger: SortByDependenciesVisit re-enters a DotNetProjectInfo whose visited flag is still true (in-process). This means project A depends on B and B (transitively) depends on A, via CsProjPath matching in item.Dependencies.
Common situations: Two projects reference each other (ProjectReference cycle); a newly added reference closes a cycle across three or more projects; merged solutions that previously had isolated cycles; refactoring that introduced a back-reference; shared/abstractions projects that accidentally reference a downstream project.
Related errors
- Build failed!
- There are more than 1 config (abp-build-config.json) file in
- There is no solution file (*.sln or *.slnx) and {_buildConfi
- Remote origin is null for given repository !
- Couldn't find repository name using remote origin url !
AI-assisted analysis of abpframework/abp@7ed43b1931 (2026-08-13).
Data as JSON: /api/errors/420365323b8968c5.
Report an issue: GitHub.