Skip to main content

How to Resolve Error "CS0729: Type 'type' is defined in this assembly, but a type forwarder is specified for it" in C#

The Compiler Error CS0729 is a logical contradiction error related to Type Forwarding. The message reads: "Type 'MyClass' is defined in this assembly, but a type forwarder is specified for it".

Type Forwarding is a feature used when refactoring assemblies (DLLs). It allows you to move a class from Assembly A to Assembly B without breaking applications that were compiled against Assembly A. Assembly A keeps a "signpost" (Attribute) saying: "I don't have this class anymore; look in Assembly B."

The error occurs when an assembly contains both the actual source code definition of the class and the signpost saying the class is elsewhere. A type cannot simultaneously exist inside the assembly and be forwarded outside of it.

Understanding Type Forwarding

The attribute [TypeForwardedTo] is found in the System.Runtime.CompilerServices namespace. It is applied at the assembly level (usually in AssemblyInfo.cs or at the top of a file).

  • Correct Usage: You moved MyClass to NewLib.dll. In OldLib.dll, you delete the class code and add [assembly: TypeForwardedTo(typeof(MyClass))].
  • Incorrect Usage: You add the attribute to OldLib.dll, but you forget to delete the class code from OldLib.dll.

Scenario: The Contradiction

This error usually happens during a refactoring process where a developer intends to move a type but hasn't finished the process, or accidentally copies an attribute from another project.

Example of error: in this example, the project defines Widget explicitly, but also tries to forward Widget to another assembly.

using System.Runtime.CompilerServices;

// The Attribute says: "Widget is NOT here. It is in another assembly referenced by this project."
[assembly: TypeForwardedTo(typeof(Widget))]

namespace MyApp
{
// The Code says: "Widget IS here."
// ⛔️ Error CS0729: Type 'Widget' is defined in this assembly,
// but a type forwarder is specified for it.
public class Widget
{
public int Id { get; set; }
}
}

Solution 1: Keep the Definition (Remove Forwarder)

If your intention is for the class to live in this assembly (the one you are currently compiling), then the Type Forwarder is wrong.

Solution: simply remove the [TypeForwardedTo] attribute.

using System.Runtime.CompilerServices;

// ✅ Correct: Attribute removed.
// [assembly: TypeForwardedTo(typeof(Widget))] <--- Deleted

namespace MyApp
{
// The class remains defined here.
public class Widget
{
public int Id { get; set; }
}
}

Solution 2: Move the Type (Remove Definition)

If your intention was to move Widget to a new library (e.g., NewLibrary.dll) while keeping the current library (OldLibrary.dll) compatible with older apps, you must delete the code from the current project.

Solution:

  1. Reference the New Library: Ensure your current project references the DLL containing the actual Widget.
  2. Delete the Code: Remove the class definition from the current project.
  3. Keep the Forwarder: The attribute remains to point to the reference.
using System.Runtime.CompilerServices;

// ✅ Correct: The attribute points to 'Widget'.
// The compiler resolves 'typeof(Widget)' by looking at the REFERENCED assembly (NewLibrary.dll),
// not the source code of this file.
[assembly: TypeForwardedTo(typeof(Widget))]

namespace MyApp
{
// ✅ Correct: Class definition removed.
// public class Widget { ... } <--- Deleted
}
note

For this to work, typeof(Widget) must resolve. This implies you have added a Project Reference or Assembly Reference to the destination library.

Conclusion

CS0729 is a conflict between your code and your metadata attributes.

  1. Decide Location: Where should MyClass live?
  2. If Here: Delete the [TypeForwardedTo] attribute.
  3. If There: Delete the class MyClass { ... } code block from the current project and ensure you reference the destination assembly.