Skip to main content

How to Resolve Error "CS0731: The type forwarder for type 'type' in assembly 'assembly' causes a cycle" in C#

The Compiler Error CS0731 is a circular dependency error related to Type Forwarding. The message reads: "The type forwarder for type 'MyClass' in assembly 'LibA' causes a cycle".

Type Forwarding is a mechanism that allows you to move a type from one assembly (DLL) to another without recompiling the applications that use it. The original assembly contains a "pointer" (TypeForwardedTo) telling the runtime to look for the type in the new assembly.

CS0731 occurs when you create an infinite loop of these pointers. For example, Assembly A tells the runtime to look in Assembly B, but Assembly B tells the runtime to look back in Assembly A. Since the type definition is never found, the compiler flags this cycle as a fatal error.

Understanding Type Forwarding Cycles

When the Common Language Runtime (CLR) loads a type, it follows the forwarding attributes.

  • Valid: AssemblyA -> forwards to -> AssemblyB (Definition found inside B).
  • Cycle (Error): AssemblyA -> forwards to -> AssemblyB -> forwards to -> AssemblyA.

The type must eventually "land" in an assembly that actually contains the source code (class MyType { ... }). If the chain loops, resolution is impossible.

Scenario: The Infinite Loop

This error often happens during complex refactoring of large solutions where types are moved between libraries, and developers forget to remove the old forwarding attributes from the target library.

Setup: imagine two projects: OldLibrary and NewLibrary. You intend to move Widget to NewLibrary.

Project 1: OldLibrary.dll

using System.Runtime.CompilerServices;

// "I don't have Widget anymore. Go look in NewLibrary."
[assembly: TypeForwardedTo(typeof(Widget))]

Project 2: NewLibrary.dll

using System.Runtime.CompilerServices;

// ⛔️ Error CS0731: Cycle detected.
// By mistake, this assembly ALSO has a forwarder pointing back to OldLibrary,
// or it references a third assembly that points back to OldLibrary.
[assembly: TypeForwardedTo(typeof(Widget))]

The compiler sees that resolving Widget in OldLibrary requires NewLibrary, which requires OldLibrary.

Solution 1: Locate the Definition (Break the Cycle)

To fix this, identify which assembly is supposed to hold the actual code for the class. That assembly must contain the class definition and must not contain a TypeForwardedTo attribute for that class.

Solution: assume NewLibrary is the new home for Widget.

Step 1: Check OldLibrary Keep the forwarder here so existing apps still work.

// OldLibrary.dll
[assembly: TypeForwardedTo(typeof(Widget))]
// (Ensure referencing NewLibrary)

Step 2: Check NewLibrary Remove the forwarder. Add the class code.

// NewLibrary.dll

// ✅ Correct: Remove the [TypeForwardedTo] attribute.
// Define the class directly.
public class Widget
{
public void Run() { }
}

Solution 2: Check Transitive References

Cycles can be indirect (A -> B -> C -> A). If you have a multi-project solution, verify the chain.

  1. Project A: Forwards to Project B.
  2. Project B: Forwards to Project C.
  3. Project C: MUST define the type. If Project C forwards back to A or B, you have a CS0731 error.

Fix: Ensure the chain is linear and ends at the definition.

Conclusion

CS0731 is a configuration error in your assembly attributes.

  1. Trace the path: Look at [assembly: TypeForwardedTo(...)] in all your projects.
  2. Find the Loop: Identify where the pointers circle back.
  3. Define the Type: Ensure exactly one assembly contains the actual class or struct definition and zero forwarders for that specific type.