pardeike/Harmony · error · InvalidOperationException
Multiple loaded HarmonySharedState types prevent safe…
Error message
Multiple loaded HarmonySharedState types prevent safe shared patch updates
What it means
HarmonySharedState stores patch state in a dynamically generated assembly-level type named after the shared-state module. GetOrCreateSharedStateType scans all loaded assemblies for a type with that name; if more than one such assembly/type is loaded (e.g. the same assembly loaded twice or two Harmony copies in different load contexts), safe shared patch updates are impossible and it throws InvalidOperationException.
Solutions
- Remove duplicate Harmony DLLs so exactly one Harmony assembly (and thus one shared-state type) is loaded
- Ensure all plugins reference a shared Harmony instance instead of bundling their own copies
- Unify assembly load contexts so the Harmony assembly resolves to one loaded copy
- Upgrade to a Harmony version that handles multiple shared-state assemblies more gracefully, if available
Example fix
// before (each plugin ships its own) plugins/ModA/0Harmony.dll plugins/ModB/0Harmony.dll // after (single shared copy) plugins/0Harmony.dll // ModA and ModB both reference this one
Defensive patterns
Strategy: validation
Validate before calling
var dupes = AppDomain.CurrentDomain.GetAssemblies()
.Where(a => a.GetName().Name == "0Harmony").Select(a => a.FullName).ToList();
if (dupes.Count > 1) throw new InvalidOperationException("Multiple Harmony assemblies loaded: " + string.Join(", ", dupes)); Try / catch
try { harmony.Patch(...); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Multiple loaded HarmonySharedState")) { /* resolve duplicate assemblies before continuing */ } Prevention
- Ship exactly one Harmony DLL per application domain; share it across plugins
- Avoid loading the same assembly twice via different load contexts or byte-loading
- For mod loaders, use a shared/common Harmony package dependency
- Log loaded Harmony assemblies at startup to catch duplicates early
When it happens
Trigger: GetOrCreateSharedStateType finding two or more distinct types named HarmonySharedState across AppDomain.CurrentDomain.GetAssemblies() — typically the Harmony assembly loaded twice (different paths/versions), plugin load contexts (AssemblyLoadContext) duplicating assemblies, or byte-loading Harmony from multiple sources.
Common situations: Unity/BepInEx mods each bundling their own Harmony 2.x DLL; hot-reload creating duplicate assemblies; mixing NuGet Harmony with a bundled copy in the same app domain.
Related errors
- The type must declare an empty constructor (the constructor…
- position( ) + count( ) > buffer.Length( )
- Unbalanced exception markers – cannot rewrite.
- Unsupported inline signature parameter type
- Unsupported generic callsite element
AI-assisted analysis of pardeike/Harmony@e7872dc170 (2026-09-15).
Data as JSON: /api/errors/b08ad562900cf3c3.
Report an issue: GitHub.
Appendix: source
Thrown at Harmony/Internal/HarmonySharedState.cs:103
// copy 'originals' over to our fields
originals = [];
if (originalsField != null) // may not exist in older versions
originals = (Dictionary<MethodInfo, MethodBase>)originalsField.GetValue(null);
// copy 'originalsMono' over to our fields
originalsMono = [];
if (originalsMonoField != null) // may not exist in older versions
originalsMono = (Dictionary<long, MethodBase[]>)originalsMonoField.GetValue(null);
}
}
// creates a dynamic 'global' type if it does not exist
static Type GetOrCreateSharedStateType()
{
var existing = AppDomain.CurrentDomain.GetAssemblies()
.Where(assembly => assembly.GetName().Name == name)
.Select(assembly => assembly.GetType(name, false)).Where(type => type is not null).Distinct().ToArray();
if (existing.Length > 1) throw new InvalidOperationException("Multiple loaded HarmonySharedState types prevent safe shared patch updates");
if (existing.Length == 1) return existing[0];
using var module = ModuleDefinition.CreateModule(name, new ModuleParameters() { Kind = ModuleKind.Dll, ReflectionImporterProvider = MMReflectionImporter.Provider });
var attr = Mono.Cecil.TypeAttributes.Public | Mono.Cecil.TypeAttributes.Abstract | Mono.Cecil.TypeAttributes.Sealed | Mono.Cecil.TypeAttributes.Class;
var typedef = new TypeDefinition("", name, attr) { BaseType = module.TypeSystem.Object };
module.Types.Add(typedef);
typedef.Fields.Add(new FieldDefinition(
"state",
Mono.Cecil.FieldAttributes.Public | Mono.Cecil.FieldAttributes.Static,
module.ImportReference(typeof(Dictionary<MethodBase, byte[]>))
));
typedef.Fields.Add(new FieldDefinition(
"originals",
Mono.Cecil.FieldAttributes.Public | Mono.Cecil.FieldAttributes.Static,
module.ImportReference(typeof(Dictionary<MethodInfo, MethodBase>))
));
View on GitHub (pinned to e7872dc170)