mono/mono · critical
Error: Loaded assembly '%s' doesn't match original file name
Error message
Error: Loaded assembly '%s' doesn't match original file name '%s'. Set MONO_PATH to the assembly's location.
What it means
In AOT mode, after loading an assembly Mono re-opens the same filename with mono_image_open and compares img->name against assembly->image->name. If they differ, the loader resolved the file to a different assembly than the one matched by name (an assembly-identity mismatch), and it exits(1). The message tells the user to set MONO_PATH to the assembly's real location.
Source
Thrown at mono/mini/driver.c:1441
for (i = 0; i < main_args->argc; ++i) {
assembly = mono_domain_assembly_open_internal (main_args->domain, mono_domain_default_alc (main_args->domain), main_args->argv [i]);
if (!assembly) {
if (mono_is_problematic_file (main_args->argv [i])) {
fprintf (stderr, "Info: AOT of problematic assembly %s skipped. This is expected.\n", main_args->argv [i]);
continue;
} else {
fprintf (stderr, "Can not open image %s\n", main_args->argv [i]);
exit (1);
}
}
/* Check that the assembly loaded matches the filename */
{
MonoImageOpenStatus status;
MonoImage *img;
img = mono_image_open (main_args->argv [i], &status);
if (img && strcmp (img->name, assembly->image->name)) {
fprintf (stderr, "Error: Loaded assembly '%s' doesn't match original file name '%s'. Set MONO_PATH to the assembly's location.\n", assembly->image->name, img->name);
exit (1);
}
}
res = mono_compile_assembly (assembly, main_args->opts, main_args->aot_options, &aot_state);
if (res != 0) {
fprintf (stderr, "AOT of image %s failed.\n", main_args->argv [i]);
exit (1);
}
}
if (aot_state) {
res = mono_compile_deferred_assemblies (main_args->opts, main_args->aot_options, &aot_state);
if (res != 0) {
fprintf (stderr, "AOT of mode-specific deferred assemblies failed.\n");
exit (1);
}
}
} else {
assembly = mono_domain_assembly_open_internal (main_args->domain, mono_domain_default_alc (main_args->domain), main_args->file);View on GitHub (pinned to 0f53e9e151)
Solutions
- Set MONO_PATH to the exact directory containing the assembly you intend to AOT: export MONO_PATH=/abs/path/to/asm.
- Remove or rename the conflicting same-named assembly elsewhere in the search path.
- Pass the full absolute path to --aot instead of relying on search.
- Verify the assembly's AssemblyName matches the file's expected identity (monodis --assembly).
Example fix
# before: MONO_PATH resolves a different Newtonsoft.Json mono --aot Newtonsoft.Json.dll # after MONO_PATH=/app/libs mono --aot /app/libs/Newtonsoft.Json.dll
Defensive patterns
Strategy: validation
Validate before calling
# Ensure the requested file's AssemblyName matches what mono will resolve
monodis --assembly "$ASM" | grep -q "Name: $EXPECTED" || { echo "identity mismatch"; exit 1; }
export MONO_PATH="$(cd "$(dirname "$ASM")" && pwd)" Prevention
- Use absolute paths and set MONO_PATH to the assembly's directory.
- Avoid having same-named assemblies in multiple search-path folders.
- Verify AssemblyName with monodis --assembly before AOT.
When it happens
Trigger: MONO_PATH or the default search path causes Mono to load an assembly whose AssemblyName does not match the file requested — typically because a different version or a same-named assembly in another directory was picked up. The strong/simple name comparison fails.
Common situations: Multiple assemblies with the same filename in different directories; MONO_PATH pointing at a shared GAC-like folder with a different version; shadow-copy or packaging putting the wrong file at the expected name; case-insensitive filesystem collisions.
Related errors
- Can not open image %s
- AOT of image %s failed.
- AOT of mode-specific deferred assemblies failed.
- Cannot open agent assembly '%s': %s.
- max-heap-size must be at least %dMb.
AI-assisted analysis of mono/mono@0f53e9e151 (2026-08-13).
Data as JSON: /api/errors/ec36f123c4e5dd38.
Report an issue: GitHub.