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.