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

  1. Identify the cycle: the exception stack trace shows the Visit chain -- inspect the assembly names involved.
  2. Break the circular reference by moving shared code into a third assembly that both depend on, or by removing one direction of the reference.
  3. Check all .asmdef files for mutual AssemblyDefinitionReference entries and eliminate bidirectional edges.
  4. 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

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


AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13). Data as JSON: /api/errors/4e95908d9556e2e6. Report an issue: GitHub.