{"record":{"id":"420365323b8968c5","repo":"abpframework/abp","slug":"cyclic-dependency-found-item-item","errorCode":null,"errorMessage":"Cyclic dependency found! Item: {item}","messagePattern":"Cyclic dependency found! Item: (.+?)","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/DefaultBuildProjectListSorter.cs","lineNumber":42,"sourceCode":"        }\n\n        return sorted;\n    }\n\n    private void SortByDependenciesVisit(\n        List<DotNetProjectInfo> source,\n        DotNetProjectInfo item,\n        List<DotNetProjectInfo> sorted,\n        Dictionary<DotNetProjectInfo, bool> visited)\n    {\n        bool inProcess;\n        var alreadyVisited = visited.TryGetValue(item, out inProcess);\n\n        if (alreadyVisited)\n        {\n            if (inProcess)\n            {\n                throw new ArgumentException(\"Cyclic dependency found! Item: \" + item);\n            }\n        }\n        else\n        {\n            visited[item] = true;\n\n            var dependencies = item.Dependencies;\n            if (dependencies != null)\n            {\n                foreach (var dependency in dependencies)\n                {\n                    var dependencyItem = source.FirstOrDefault(e => e.CsProjPath == dependency.CsProjPath);\n                    if (dependencyItem != null)\n                    {\n                        SortByDependenciesVisit(source, dependencyItem, sorted, visited);\n                    }\n                }\n            }","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/abpframework/abp/blob/7ed43b1931b9df46a50c0c59148a18645641d0df/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/DefaultBuildProjectListSorter.cs#L24-L60","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"<!-- before: ProjectA.csproj references ProjectB, ProjectB references ProjectA -->\n<ProjectReference Include=\"..\\ProjectB\\ProjectB.csproj\" />\n\n<!-- after: extract shared code into a ProjectShared that both reference, with no back-edge -->\n<!-- ProjectA -> ProjectShared, ProjectB -> ProjectShared -->","handlingStrategy":"validation","validationCode":"// Detect a project-reference cycle before invoking the sorter.\nbool HasCycle(List<DotNetProjectInfo> projects)\n{\n    var byPath = projects.ToDictionary(p => p.CsProjPath);\n    var visited = new HashSet<string>();\n    var stack = new HashSet<string>();\n    bool Dfs(string path)\n    {\n        if (stack.Contains(path)) return true;\n        if (!visited.Add(path)) return false;\n        stack.Add(path);\n        if (byPath.TryGetValue(path, out var p) && p.Dependencies != null)\n            foreach (var d in p.Dependencies)\n                if (byPath.ContainsKey(d.CsProjPath) && Dfs(d.CsProjPath)) return true;\n        stack.Remove(path);\n        return false;\n    }\n    return projects.Any(p => Dfs(p.CsProjPath));\n}\nif (HasCycle(projects)) throw new InvalidOperationException(\"Project reference cycle detected; remove the back-reference.\");","typeGuard":"// (uses validation code above; no type to guard)","tryCatchPattern":"try\n{\n    var ordered = sorter.SortByDependencies(projects);\n}\ncatch (ArgumentException ex) when (ex.Message.Contains(\"Cyclic dependency\", StringComparison.Ordinal))\n{\n    logger.LogError(ex, \"Cycle detected while ordering projects; remove the offending ProjectReference.\");\n    throw;\n}","preventionTips":["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."],"tags":["cli","build","dependencies","project-reference"],"backgroundTag":null,"analyzedSha":"7ed43b1931b9df46a50c0c59148a18645641d0df","analyzedAt":"2026-08-13T16:26:11.351Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}