egametang/ET · error · Exception
Detected cyclic dependency!
Error message
Detected cyclic dependency!
What it means
Thrown by AssemblySorter.TopologicalSorter.Visit when a node is re-encountered while it is still in the tempMarks set (i.e. on the current DFS path). This is the textbook cycle-detection check in a topological sort and indicates two or more assemblies reference each other in a circular dependency chain.
Source
Thrown at Packages/cn.etetet.hybridclr/Scripts/Editor/Share/Meta/AssemblySorter.cs:46
List<Node> sorted = new List<Node>();
HashSet<Node> visited = new HashSet<Node>();
HashSet<Node> tempMarks = new HashSet<Node>();
foreach (var node in nodes)
{
if (!visited.Contains(node))
{
Visit(node, visited, tempMarks, sorted);
}
}
return sorted;
}
private static void Visit(Node node, HashSet<Node> visited, HashSet<Node> tempMarks, List<Node> sorted)
{
if (tempMarks.Contains(node))
{
throw new Exception("Detected cyclic dependency!");
}
if (!visited.Contains(node))
{
tempMarks.Add(node);
foreach (var dependency in node.Dependencies)
{
Visit(dependency, visited, tempMarks, sorted);
}
tempMarks.Remove(node);
visited.Add(node);
sorted.Add(node);
}
}
}
private static List<string> SortAssemblyByReferenceOrder(IEnumerable<string> assemblies, Dictionary<string, HashSet<string>> refs)
{View on GitHub (pinned to 5cab01f7a8)
Solutions
- Identify the cycle: the exception stack trace shows the Visit chain -- inspect the assembly names involved.
- Break the circular reference by moving shared code into a third assembly that both depend on, or by removing one direction of the reference.
- Check all .asmdef files for mutual AssemblyDefinitionReference entries and eliminate bidirectional edges.
- If the cycle is intentional (e.g. generated code), restructure so the generator produces a DAG.
Example fix
// before: A.asmdef references B, B.asmdef references A (cycle) // after: create Shared.asmdef; A and B both reference Shared; remove A<->B edge
Defensive patterns
Strategy: validation
Validate before calling
// Before sorting, detect cycles in the assembly reference graph
var graph = BuildReferenceGraph(assemblies); // returns Dictionary<string, HashSet<string>>
if (HasCycle(graph))
Debug.LogError("Circular assembly dependency detected."); Type guard
// Type guard for a DAG: returns true if the reference graph is acyclic
static bool IsAcyclic(Dictionary<string, HashSet<string>> graph)
{
var visited = new HashSet<string>();
var stack = new HashSet<string>();
bool Dfs(string node)
{
if (stack.Contains(node)) return false;
if (!visited.Add(node)) return true;
stack.Add(node);
foreach (var dep in graph.GetValueOrDefault(node, new HashSet<string>()))
if (!Dfs(dep)) return false;
stack.Remove(node);
return true;
}
return graph.Keys.All(Dfs);
} Prevention
- Never create mutual .asmdef references; move shared code to a common dependency.
- Add a CI check that validates the assembly graph is a DAG before building.
- Review .asmdef AssemblyDefinitionReference arrays during code review for bidirectional edges.
When it happens
Trigger: SortAssemblyByReferenceOrder builds a dependency graph from each assembly's GetAssemblyRefs, then topologically sorts. If assembly A references B and B references A (directly or transitively), Visit recurses back to A while A is temp-marked and throws.
Common situations: Two .asmdef files with mutual AssemblyDefinitionReference entries; a circular project reference introduced by refactoring; hot update and AOT assemblies that inadvertently reference each other; Unity's own assembly graph has a cycle that normally does not surface but breaks HybridCLR's sort.
Related errors
- type:{type} definition could not be found. Please try `Hybri
- can't find xxxx.xcodeproj/project.pbxproj in {pathToBuiltPro
- You have not initialized HybridCLR, please install it via me
- You must run `HybridCLR/Installer` after upgrading package
- hot update assembly name cann't be empty
AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13).
Data as JSON: /api/errors/4e95908d9556e2e6.
Report an issue: GitHub.