{"record":{"id":"633b51e37c40b9a2","repo":"abpframework/abp","slug":"cyclic-dependency-found-item-item-633b51","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.Core/System/Collections/Generic/AbpListExtensions.cs","lineNumber":234,"sourceCode":"    /// <summary>\n    ///\n    /// </summary>\n    /// <typeparam name=\"T\">The type of the members of values.</typeparam>\n    /// <param name=\"item\">Item to resolve</param>\n    /// <param name=\"getDependencies\">Function to resolve the dependencies</param>\n    /// <param name=\"sorted\">List with the sortet items</param>\n    /// <param name=\"visited\">Dictionary with the visited items</param>\n    private static void SortByDependenciesVisit<T>(T item, Func<T, IEnumerable<T>> getDependencies, List<T> sorted,\n        Dictionary<T, bool> visited) where T : notnull\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 = getDependencies(item);\n            if (dependencies != null)\n            {\n                foreach (var dependency in dependencies)\n                {\n                    SortByDependenciesVisit(dependency, getDependencies, sorted, visited);\n                }\n            }\n\n            visited[item] = false;\n            sorted.Add(item);\n        }","sourceCodeStart":216,"sourceCodeEnd":252,"githubUrl":"https://github.com/abpframework/abp/blob/7ed43b1931b9df46a50c0c59148a18645641d0df/framework/src/Volo.Abp.Core/System/Collections/Generic/AbpListExtensions.cs#L216-L252","documentation":"Thrown by AbpListExtensions.SortByDependenciesVisit during topological sorting when an item is revisited while still marked in-process (visited[item] == true). That re-entrancy means the dependency graph has a cycle: A (transitively) depends on A, so no valid linear ordering exists. The exception names the offending item.","triggerScenarios":"Calling source.SortByDependencies(getDependencies) where getDependencies returns a graph containing a cycle — e.g. module A depends on B and B depends on A. Most commonly hit during ABP module loading when modules declare circular DependsOn relationships.","commonSituations":"Two ABP modules with mutual [DependsOn] attributes; a service/feature dependency cycle passed to SortByDependencies; self-dependency (an item whose getDependencies returns itself).","solutions":["Break the cycle: remove one direction of the [DependsOn] attribute or restructure so dependencies are acyclic.","Inspect the exception's item name to locate the cycle, then trace its dependencies to find the back-edge.","If the cycle is intentional, refactor to remove the dependency (e.g. via events or lazy resolution) since topological order requires a DAG.","Add a unit test asserting the dependency graph is acyclic before sorting."],"exampleFix":"// before — circular module dependency\n[DependsOn(typeof(BModule))]\npublic class AModule : AbpModule { }\n[DependsOn(typeof(AModule))] // cycle: A -> B -> A\npublic class BModule : AbpModule { }\n\n// after — break the cycle\n[DependsOn(typeof(BModule))]\npublic class AModule : AbpModule { }\npublic class BModule : AbpModule { } // remove the reverse DependsOn","handlingStrategy":"validation","validationCode":"// Detect a cycle before topological sort using a DFS with recursion-stack coloring\nstatic bool HasCycle<T>(IEnumerable<T> nodes, Func<T, IEnumerable<T>> deps, IEqualityComparer<T>? cmp = null) where T : notnull\n{\n    var state = new Dictionary<T, byte>(cmp ?? EqualityComparer<T>.Default); // 0=unseen,1=in-progress,2=done\n    bool Dfs(T n) {\n        if (state.TryGetValue(n, out var s)) return s == 1;\n        state[n] = 1;\n        foreach (var d in deps(n) ?? Enumerable.Empty<T>()) if (Dfs(d)) return true;\n        state[n] = 2; return false;\n    }\n    return nodes.Any(Dfs);\n}","typeGuard":null,"tryCatchPattern":"try { var ordered = source.SortByDependencies(getDependencies); }\ncatch (ArgumentException ex) when (ex.Message.StartsWith(\"Cyclic dependency\"))\n{ /* log the item, then break the [DependsOn] cycle and retry */ }","preventionTips":["Keep ABP module [DependsOn] graphs acyclic; never declare mutual dependencies.","Add a cycle-detection unit test over the dependency function before sorting.","Refactor intentional cycles to use events or lazy resolution."],"tags":["collections","topological-sort","cyclic-dependency","modules","abp-core"],"backgroundTag":null,"analyzedSha":"7ed43b1931b9df46a50c0c59148a18645641d0df","analyzedAt":"2026-08-13T16:26:11.351Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}