Question

Fixing Assembly Manifest Mismatch in C# (.NET): The Located Assembly's Manifest Definition Does Not Match the Assembly Reference

csharpreferencecompiler-errorsdependenciesversion

Question

I am trying to run unit tests in a C# Windows Forms application in Visual Studio 2005, and I get this error:

System.IO.FileLoadException: Could not load file or assembly 'Utility, Version=1.2.0.200, Culture=neutral, PublicKeyToken=764d581291d764f7' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
at x.Foo.FooGO()
at x.Foo.Foo2(string groupName_) in Foo.cs:line 123
at x.Foo.UnitTests.FooTests.TestFoo() in FooTests.cs:line 98

System.IO.FileLoadException: Could not load file or assembly 'Utility, Version=1.2.0.203, Culture=neutral, PublicKeyToken=764d581291d764f7' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

In my project references, I only see a reference to Utility version 1.2.0.203. The older version appears to be 1.2.0.200.

How can I figure out what is still trying to reference the old version of this DLL?

Also, I do not think that I even have the old assembly on my hard drive. Is there a tool that can help search for this old versioned assembly or identify which assembly is requesting it?

Short Answer

By the end of this page, you will understand what an assembly manifest mismatch means in C#/.NET, why it happens even when your project references look correct, and how to trace the real source of an outdated DLL reference. You will also learn practical debugging tools such as Fusion Log Viewer, dependency inspection, and common fixes like cleaning output folders, updating dependent projects, and checking transitive references.

Concept

In .NET, an assembly reference is more than just a file name. It includes identity information such as:

  • Assembly name
  • Version
  • Culture
  • Public key token

When your code or one of its dependencies asks the runtime to load an assembly, .NET tries to find an assembly whose manifest exactly matches that identity.

A typical reference might look like this:

Utility, Version=1.2.0.203, Culture=neutral, PublicKeyToken=764d581291d764f7

If the runtime finds a file named Utility.dll but its embedded manifest says it is actually version 1.2.0.200, that is a mismatch. The runtime treats that as a different assembly and throws this error:

The located assembly's manifest definition does not match the assembly reference.

Why this happens

Common causes include:

  • A project references a newer DLL, but the output folder still contains an older copy.
  • Another dependent assembly was compiled against the old version.
  • The Global Assembly Cache (GAC) contains a different version than expected.
  • A unit test runner is loading assemblies from a different folder than you expect.
  • app.config or test configuration is missing a required binding redirect.
  • One machine has stale build artifacts or copied DLLs left over from older builds.

Why this matters

Assembly loading is fundamental in .NET applications:

  • Desktop apps load shared libraries.
  • Test runners load your app plus test assemblies plus helper libraries.
  • Plugins and third-party packages rely on exact assembly identity.
  • Deployment problems often appear as assembly load failures.

Understanding assembly identity helps you debug confusing errors where the visible project reference is not the real source of the problem.

Mental Model

Think of an assembly like a book with a title, edition number, language, and publisher stamp.

Even if two books are both called Utility, the runtime does not treat them as the same unless all identifying details match.

  • Utility = title
  • 1.2.0.203 = edition
  • neutral = language
  • PublicKeyToken=... = publisher stamp

If someone asks for Utility, edition 203, and you hand them Utility, edition 200, they may look similar, but the runtime says: this is not the exact book I asked for.

That is what a manifest mismatch means: the file was found, but its identity does not match the requested identity.

Take Quiz

Syntax and Examples

In C#, you usually do not load referenced assemblies manually. The runtime does it for you based on compiled metadata.

Example of a normal reference

Suppose App.exe references Utility.dll:

using Utility;

class Program
{
    static void Main()
    {
        Helper.DoWork();
    }
}

At compile time, the application stores metadata saying which assembly identity it expects.

Example of the problem

Your app was compiled expecting:

Utility, Version=1.2.0.203

But at runtime, the folder contains:

Utility.dll  --> actually version 1.2.0.200

Then .NET throws a FileLoadException.

How to inspect an assembly version in code

You can inspect what DLL was actually loaded:

using System;
using System.Reflection;

class Program
{
    static void Main()
    {
        Assembly assembly = Assembly.Load("Utility");
        Console.WriteLine(assembly.FullName);
    }
}

Possible output:

Utility, Version=1.2.0.200, Culture=neutral, PublicKeyToken=764d581291d764f7

That tells you the actual identity of the assembly that was found.

Useful tools

Fusion Log Viewer (fuslogvw.exe)

Shows exactly:

  • which assembly was requested
  • where .NET searched
  • what file it found
  • why loading failed

ILDASM or dotPeek

Lets you inspect a compiled DLL and see which assembly versions it references.

File search tools

Search for stale copies of Utility.dll in:

  • bin
  • obj
  • test runner folders
  • shared library folders
  • the GAC

Step by Step Execution

Consider this simplified situation:

TestProject.dll -> references App.dll
App.dll -> references Utility, Version=1.2.0.203
LegacyHelper.dll -> references Utility, Version=1.2.0.200

Your unit test calls code in App.dll, but App.dll also uses LegacyHelper.dll.

What happens step by step

  1. The test runner starts loading TestProject.dll.

  2. TestProject.dll loads App.dll.

  3. App.dll begins executing code.

  4. During execution, LegacyHelper.dll is loaded.

  5. LegacyHelper.dll asks for:

    Utility, Version=1.2.0.200
    
  6. The runtime searches for a matching Utility.dll.

  7. It finds Utility.dll, but that file is actually version 1.2.0.203.

  8. The identities do not match.

  9. .NET throws:

    FileLoadException: The located assembly's manifest definition does not match the assembly reference.
    

Key insight

The project that fails is not always the project that contains the bad reference.

Often, the old reference is hidden inside:

  • another class library
  • a third-party DLL
  • a copied build output
  • a test host process
  • the GAC

Practical tracing process

  1. Clean and rebuild the full solution.
  2. Delete bin and obj folders manually.
  3. Use Fusion Log Viewer to identify the requesting assembly.
  4. Inspect referenced DLLs to see which one still points to the old version.
  5. Check the GAC for installed versions.
  6. Check test runner config files for outdated binding behavior.

Real World Use Cases

Assembly version debugging appears in many real situations:

Unit test failures

A test project may compile fine, but the test runner loads old DLLs from a previous build directory.

Shared internal libraries

A company updates Utility.dll, but one older library still references the previous version.

Desktop application deployment

A Windows Forms or WPF app is deployed with the wrong DLL copy in its installation folder.

Plugin systems

A plugin built against one version of a shared assembly fails when loaded into a host using another version.

CI/CD build servers

A build agent may keep stale artifacts between builds, causing one machine to fail while another works.

GAC-related enterprise apps

A strongly named assembly in the GAC can override what developers expect from local output folders.

Take Quiz

Real Codebase Usage

In real projects, developers usually handle assembly version issues with a few standard patterns.

1. Clean output before diagnosing

A common first step is to remove stale build artifacts:

  • delete bin/
  • delete obj/
  • rebuild all projects

This is especially important in older .NET Framework solutions.

2. Check transitive dependencies

If A references B, and B references an old Utility.dll, then A may fail even though its own reference is correct.

Developers inspect all dependent assemblies, not just the main project.

3. Use guard-style diagnostics

In startup or test bootstrap code, developers sometimes log loaded assemblies:

foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
    Console.WriteLine(assembly.FullName);
}

This helps reveal which version was actually loaded.

4. Centralize dependency updates

In multi-project solutions, developers update shared dependencies everywhere before rebuilding.

5. Use configuration when version redirection is valid

In .NET Framework apps, app.config can sometimes redirect older versions to a newer one:

<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Utility"
                          publicKeyToken="764d581291d764f7"
                          culture="neutral" />
        <bindingRedirect oldVersion="1.2.0.0-1.2.0.203"
                         newVersion="1.2.0.203" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

This only works when the newer version is compatible and the app type honors binding redirects.

6. Verify third-party and legacy binaries

A frequent real-world cause is a precompiled DLL that was never rebuilt after a dependency upgrade.

Common Mistakes

1. Only checking the main project's references

Beginners often look at just one project's References node and assume everything is correct.

But the old reference may exist in:

  • another project in the solution
  • a third-party DLL
  • a test helper assembly
  • a plugin

2. Forgetting stale bin and obj folders

Broken build outputs can survive after reference changes.

Broken situation

  • Project reference updated to 1.2.0.203
  • bin\Debug\Utility.dll still contains 1.2.0.200

Fix

Delete output folders manually and rebuild.

3. Ignoring the GAC

If the assembly is strongly named, the runtime may load it from the GAC.

A machine can have an old version installed even when the local file system looks clean.

4. Searching by file name only

Two DLLs can share the same file name but have different assembly identities.

Always inspect the embedded version and public key token, not just the file name.

5. Assuming the missing version must physically exist somewhere

Sometimes the runtime error mentions an old version because a compiled assembly requests it. The old DLL file does not need to be present for the error to occur.

6. Adding random copies of DLLs to fix it

This often makes things worse.

Bad approach

Copy Utility.dll from another machine into bin\Debug

This may hide the real problem or create a different mismatch.

7. Forgetting config files for test runners

A unit test project may use a separate config file from the main application. A redirect in the app config may not apply to tests unless the test host uses it.

Comparisons

ConceptWhat it meansTypical symptomCommon fix
Assembly not found.NET cannot locate the DLL at allFileNotFoundExceptionAdd/copy the correct DLL, fix probing path
Manifest mismatchDLL was found, but identity does not matchFileLoadException with manifest definition mismatchUpdate references, clean outputs, binding redirect, rebuild dependencies
Bad image formatDLL exists but is not valid for the process architectureBadImageFormatExceptionMatch x86/x64/AnyCPU
Compile-time reference errorProject cannot compile due to missing referenceBuild error in Visual StudioFix project/package references

Reference vs actual file

ItemReference metadataPhysical DLL file
Stored inCompiled assembly manifestFile system or GAC
ContainsExpected identityActual identity
Can be different?YesYes
Mismatch resultRuntime failureRuntime failure

Project reference vs transitive dependency

SourceVisible in your project?Can cause this error?
Direct referenceYesYes
Reference inside another DLLOften noYes
GAC-installed assemblyNoYes
Test runner dependencyOften noYes
Take Quiz

Cheat Sheet

Quick diagnosis checklist

  1. Check the exact assembly name, version, and public key token in the error.
  2. Delete all bin and obj folders.
  3. Rebuild the full solution.
  4. Use Fusion Log Viewer (fuslogvw.exe).
  5. Inspect dependent DLLs for old references.
  6. Check the GAC if the assembly is strongly named.
  7. Verify test runner config and output folder.
  8. Add a binding redirect if appropriate for .NET Framework.

Important rule

A .NET assembly reference is based on:

Name + Version + Culture + PublicKeyToken

A matching file name alone is not enough.

Common tools

  • fuslogvw.exe — assembly bind logging
  • ildasm.exe — inspect assembly metadata
  • dotPeek / ILSpy — inspect references in DLLs
  • Windows file search / command line search — find duplicate DLLs
  • gacutil — inspect GAC entries

Useful commands and actions

Manually clean outputs

Delete bin\ and obj\ folders in every project

Log loaded assemblies in code

foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
{
    Console.WriteLine(asm.FullName);
}

Look for binding redirects

<bindingRedirect oldVersion="1.2.0.0-1.2.0.203" newVersion="1.2.0.203" />

Key troubleshooting question

Ask:

Which assembly is requesting the old version?

That is usually more useful than asking:

Where is the old DLL file?

FAQ

What does "manifest definition does not match the assembly reference" mean?

It means .NET found a DLL file, but the assembly identity inside that file does not match the version or strong name that was requested.

Why do I see an old version when my references show only the new one?

Because another dependency may still reference the old version, or a stale DLL may still exist in the output folder, test host folder, or GAC.

How do I find which assembly is requesting the old DLL version?

Use Fusion Log Viewer (fuslogvw.exe). It shows the bind request and often reveals the assembly that triggered it.

Can this happen even if the old DLL is not on my machine?

Yes. The error can happen simply because a compiled assembly requests the old version. The old DLL does not have to exist for the request to appear in the error.

Should I just copy the new DLL into the output folder?

Only if you know the requesting assembly expects that exact version or a binding redirect is in place. Randomly copying files often hides the real dependency issue.

Can binding redirects fix this?

Often yes in .NET Framework applications, if the newer assembly is compatible and the application or test host uses the correct config file.

Does the GAC matter here?

Yes. For strongly named assemblies, the GAC can affect what version the runtime loads.

Why does this happen more often in unit tests?

Test runners often load assemblies from separate folders and may use different config files from your main application.

Take Quiz

Mini Project

Description

Create a small diagnostic console program that lists all currently loaded assemblies and attempts to load a target assembly by name. This project helps you understand how .NET identifies assemblies and gives you a practical way to inspect versions during debugging.

Goal

Build a simple assembly inspection tool that shows assembly full names and helps verify which version of a DLL is being loaded.

Requirements

  • Create a C# console application.
  • Print all assemblies currently loaded in the current AppDomain.
  • Attempt to load an assembly by a simple name such as Utility.
  • Display the assembly full name if loading succeeds.
  • Catch and print assembly loading exceptions clearly.
Take Quiz

Keep learning

Related questions

View more