Ensure an included .DLL does not get analyzed by Burst compiler?

I’ve got a plugin I’m working on which uses Harmony, an external .DLL. Everything referencing Harmony methods works perfectly on runtime, however, when opening a project with the .DLL included, Burst throws an error.

Projects without Burst do not have this problem. Any suggestions as to how I can ensure Burst doesn’t analyze the included .DLL?

I’ve tried playing with assembly definitions to ensure there’s no references to the Unity editor, to no avail.

The full error is this:

Failed to find entry-points:
System.Exception: Error while loading assembly references for Assembly-CSharp-Editor ---> System.Exception: Error while hashing assembly /Users/mobiusteapot/Documents/Programming/gitRepo/URPPlayground/Packages/UnityEditor-GameViewFullscreen/FullscreenEditor/Plugins/Harmony/net48/0Harmony.dll ---> System.AggregateException: One or more errors occurred. (Error while hashing type reference '10000D0' in assembly '0Harmony.dll') ---> System.Exception: Error while hashing type reference '10000D0' in assembly '0Harmony.dll' ---> System.BadImageFormatException: Read out of bounds.
  at System.Reflection.Throw.OutOfBounds () [0x00005] in <dd9f65e0a5bd49ea8090db671948b5fc>:0 
  at System.Reflection.Internal.MemoryBlock.PeekHeapReference (System.Int32 offset, System.Boolean smallRefSize) [0x0000b] in <dd9f65e0a5bd49ea8090db671948b5fc>:0 
  at System.Reflection.Metadata.Ecma335.AssemblyRefTableReader.GetName (System.Int32 rowId) [0x0000b] in <dd9f65e0a5bd49ea8090db671948b5fc>:0 
  at System.Reflection.Metadata.AssemblyReference.get_Name () [0x00020] in <dd9f65e0a5bd49ea8090db671948b5fc>:0 
  at Burst.Compiler.IL.Hashing.CacheBuilder.Util.SrmExtensions.GetAssemblyNameReference (System.Reflection.Metadata.AssemblyReference& assemblyReference, System.Reflection.Metadata.MetadataReader metadataReader) [0x00000] in <69b504cf34c54d688310e60f1ce29d2e>:0 
  at Burst.Compiler.IL.Hashing.CacheBuilder.Util.CachingMetadataReader.GetAssemblyNameReferenceImpl (System.Reflection.Metadata.AssemblyReferenceHandle handle) [0x0000d] in <69b504cf34c54d688310e60f1ce29d2e>:0 
  at System.Collections.Concurrent.ConcurrentDictionary`2[TKey,TValue].GetOrAdd (TKey key, System.Func`2[T,TResult] valueFactory) [0x00034] in <3aacbe608a2f468eb6bb1c15e219490d>:0 
  at Burst.Compiler.IL.Hashing.CacheBuilder.Util.CachingMetadataReader.GetAssemblyNameReference (System.Reflection.Metadata.AssemblyReferenceHandle handle) [0x00000] in <69b504cf34c54d688310e60f1ce29d2e>:0 
  at Burst.Compiler.IL.Hashing.CacheBuilder.Util.SrmExtensions.WriteAssemblyNameTo (System.Reflection.Metadata.TypeReference& typeReference, Burst.Compiler.IL.Helpers.Hash128Builder builder, Burst.Compiler.IL.Hashing.CacheBuilder.Util.CachingMetadataReader reader, Burst.Compiler.TargetFramework targetFramework) [0x00037] in <69b504cf34c54d688310e60f1ce29d2e>:0 
  at Burst.Compiler.IL.Hashing.CacheBuilder.ILHasher.HashTypeReferenceImpl (System.Reflection.Metadata.TypeReferenceHandle typeReferenceHandle) [0x00089] in <69b504cf34c54d688310e60f1ce29d2e>:0 
  at Burst.Compiler.IL.Hashing.CacheBuilder.ILHasher.HashTypeReference (System.Reflection.Metadata.TypeReferenceHandle typeReferenceHandle) [0x00000] in <69b504cf34c54d688310e60f1ce29d2e>:0 
   --- End of inner exception stack trace ---
  at Burst.Compiler.IL.Hashing.CacheBuilder.ILHasher.HashTypeReference (System.Reflection.Metadata.TypeReferenceHandle typeReferenceHandle) [0x00031] in <69b504cf34c54d688310e60f1ce29d2e>:0 
  at Burst.Compiler.IL.Hashing.CacheBuilder.ILHasher+<>c__DisplayClass14_0.<HashImpl>b__6 (System.Reflection.Metadata.TypeReferenceHandle typeReferenceHandle, System.Threading.Tasks.ParallelLoopState loopState, System.Int64 i) [0x00000] in <69b504cf34c54d688310e60f1ce29d2e>:0 
  at Burst.Compiler.IL.Hashing.CacheBuilder.ILHasher.ForEach[T] (System.Collections.Generic.IEnumerable`1[T] elements, System.Action`3[T1,T2,T3] callback) [0x00018] in <69b504cf34c54d688310e60f1ce29d2e>:0 
  at Burst.Compiler.IL.Hashing.CacheBuilder.ILHasher+<>c__DisplayClass14_0.<HashImpl>b__1 () [0x00000] in <69b504cf34c54d688310e60f1ce29d2e>:0 
  at System.Threading.Tasks.Task.InnerInvoke () [0x0000f] in <3aacbe608a2f468eb6bb1c15e219490d>:0 
  at System.Threading.Tasks.Task.Execute () [0x00000] in <3aacbe608a2f468eb6bb1c15e219490d>:0 
   --- End of inner exception stack trace ---
  at System.Threading.Tasks.Task.WaitAll (System.Threading.Tasks.Task[] tasks, System.Int32 millisecondsTimeout, System.Threading.CancellationToken cancellationToken) [0x001c8] in <3aacbe608a2f468eb6bb1c15e219490d>:0 
  at System.Threading.Tasks.Task.WaitAll (System.Threading.Tasks.Task[] tasks, System.Int32 millisecondsTimeout) [0x00000] in <3aacbe608a2f468eb6bb1c15e219490d>:0 
  at System.Threading.Tasks.Task.WaitAll (System.Threading.Tasks.Task[] tasks) [0x00000] in <3aacbe608a2f468eb6bb1c15e219490d>:0 
  at Burst.Compiler.IL.Hashing.CacheBuilder.ILHasher.HashImpl () [0x00243] in <69b504cf34c54d688310e60f1ce29d2e>:0 
  at Burst.Compiler.IL.Hashing.CacheBuilder.ILHasher.HashAssembly (System.String filePath, System.Threading.Tasks.TaskFactory taskFactory, Burst.Compiler.TargetFramework targetFramework) [0x00009] in <69b504cf34c54d688310e60f1ce29d2e>:0 
   --- End of inner exception stack trace ---
  at Burst.Compiler.IL.Hashing.CacheBuilder.ILHasher.HashAssembly (System.String filePath, System.Threading.Tasks.TaskFactory taskFactory, Burst.Compiler.TargetFramework targetFramework) [0x0002e] in <69b504cf34c54d688310e60f1ce29d2e>:0 
  at Burst.Compiler.IL.Hashing.CacheRuntime.HashCacheLoader.CreateHashingResult (Mono.Cecil.AssemblyNameReference assemblyNameReference, Burst.Compiler.IL.AssemblyLoader assemblyLoader, Burst.Compiler.IL.Helpers.DebugLogWriter debugLogWriter) [0x001b9] in <69b504cf34c54d688310e60f1ce29d2e>:0 
  at Burst.Compiler.IL.Hashing.CacheRuntime.HashCacheAssemblyStore.GetAssemblyState (System.String assemblyName, Burst.Compiler.IL.AssemblyLoader assemblyLoader) [0x000a0] in <69b504cf34c54d688310e60f1ce29d2e>:0 
  at Burst.Compiler.IL.Server.EntryPointMethodFinder.LoadAllAssemblyReferences (Mono.Cecil.AssemblyDefinition asmDef, System.Collections.Generic.Dictionary`2[TKey,TValue] visited, System.Collections.Generic.Dictionary`2[TKey,TValue] jobProducers, Burst.Compiler.IL.Hashing.CacheRuntime.HashCacheAssemblyStore assemblyStore, Burst.Compiler.IL.AssemblyLoader assemblyLoader) [0x00025] in <69b504cf34c54d688310e60f1ce29d2e>:0 
  at Burst.Compiler.IL.Server.EntryPointMethodFinder.LoadAllAssemblyReferences (Mono.Cecil.AssemblyDefinition asmDef, System.Collections.Generic.Dictionary`2[TKey,TValue] visited, System.Collections.Generic.Dictionary`2[TKey,TValue] jobProducers, Burst.Compiler.IL.Hashing.CacheRuntime.HashCacheAssemblyStore assemblyStore, Burst.Compiler.IL.AssemblyLoader assemblyLoader) [0x001de] in <69b504cf34c54d688310e60f1ce29d2e>:0 
  at Burst.Compiler.IL.Server.EntryPointMethodFinder.FindEntryPoints (System.String[] rootAssemblyNames, Burst.Compiler.IL.Hashing.CacheRuntime.HashCacheAssemblyStore assemblyStore, Burst.Compiler.IL.AssemblyLoader assemblyLoader, Burst.Compiler.IL.NativeCompilerOptions options, Burst.Compiler.IL.Server.ProfileDelegate profileCallback, System.Boolean includeRootAssemblyReferences, System.Boolean splitTargets) [0x00071] in <69b504cf34c54d688310e60f1ce29d2e>:0 
   --- End of inner exception stack trace ---
  at Burst.Compiler.IL.Server.EntryPointMethodFinder.FindEntryPoints (System.String[] rootAssemblyNames, Burst.Compiler.IL.Hashing.CacheRuntime.HashCacheAssemblyStore assemblyStore, Burst.Compiler.IL.AssemblyLoader assemblyLoader, Burst.Compiler.IL.NativeCompilerOptions options, Burst.Compiler.IL.Server.ProfileDelegate profileCallback, System.Boolean includeRootAssemblyReferences, System.Boolean splitTargets) [0x00094] in <69b504cf34c54d688310e60f1ce29d2e>:0 
  at Burst.Compiler.IL.Server.CompilerServer+<>c__DisplayClass18_1.<FindMethods>b__0 (Burst.Compiler.IL.Server.Caching.CacheManager cacheManager) [0x0005e] in <69b504cf34c54d688310e60f1ce29d2e>:0 
  at Burst.Compiler.IL.Server.CompilerServer+<>c__DisplayClass26_0`1[TResult].<RunTask>b__0 () [0x00145] in <69b504cf34c54d688310e60f1ce29d2e>:0 
  at Burst.Compiler.IL.Server.CompilerServer.RunTask[TResult] (Burst.Compiler.IL.Server.TargetKey target, System.String taskName, System.String[] assemblyFolders, System.Threading.CancellationToken cancellationToken, System.Func`2[T,TResult] function) [0x00131] in <69b504cf34c54d688310e60f1ce29d2e>:0 
  at Burst.Compiler.IL.Server.CompilerServer.FindMethods (Burst.Compiler.IL.Server.CompilerServerOptions options, Burst.Compiler.IL.Aot.AotCompilerOptions aotOptions, Burst.Compiler.IL.AssemblyDefinesDict assemblyDefines, Burst.Compiler.IL.Server.TargetKey target, Burst.Compiler.IL.Server.Caching.CacheManager cacheManager, Burst.Compiler.IL.CompilerStatistics stats, System.Threading.CancellationToken cancellationToken) [0x00299] in <69b504cf34c54d688310e60f1ce29d2e>:0 
  at Burst.Compiler.IL.Server.CompilerServer+<>c__DisplayClass26_0`1[TResult].<RunTask>b__0 () [0x00145] in <69b504cf34c54d688310e60f1ce29d2e>:0 
  at Burst.Compiler.IL.Server.CompilerServer.RunTask[TResult] (Burst.Compiler.IL.Server.TargetKey target, System.String taskName, System.String[] assemblyFolders, System.Threading.CancellationToken cancellationToken, System.Func`2[T,TResult] function) [0x00131] in <69b504cf34c54d688310e60f1ce29d2e>:0 
  at Burst.Compiler.IL.Server.CompilerServer.Compile (Burst.Compiler.IL.Server.CompilerServerOptions options, Burst.Compiler.IL.Server.CompilationMessageStreamer streamer, System.Threading.CancellationToken cancellationToken) [0x001ca] in <69b504cf34c54d688310e60f1ce29d2e>:0 

While compiling job:

Hi @ez9002,

We have seen a similar issue before. In that case, it was caused by invalid metadata in 0Harmony.dll. At that time, a workaround was to use a locally build “Fat” release build of Harmony, build from the latest code in the Harmony repo on GitHub.

This might also work for you. If it doesn’t, then please file a bug.

Thank you for the insight. I spent a hot minute trying different .Net versions of Harmony, but any that were compatible with Unity seemed to throw the error. I was unable to have any luck with compiling my own from any of the branches Harmony has available.

I can confirm, when I run peverify 0Harmony.dll /md, there are issues in Harmony’s metadata, but I was unable to pin down the culprit, or fix it.

I filed a ticket. After digging into this issue further, it seems like broken metadata may also not behave nicely with il2cpp, however, for situations where I’d like to opt out of Burst and IL2CPP for a specific project, it would be really nice to have the option to ensure the .dll is ignored, since there aren’t errors on runtime, just this error on domain reload.

We’re running into the same issue (Unity 6.2; apparently only on Mac, though). Will have a look at creating a custom build. But yeah, also agree, would be nice if Burst could simply be made to not touch this assembly.

We’re using it entirely in the editor only to patch out UnityEditor.LevelPlay.LevelPlayInstallMenuItem and UnityEditor.InAppPurchasing.InAppPurchasingInstallMenuItem which Unity runs in every single Unity project regardless of whether they’re using IAP and/or ads. The two combined often keep an entire CPU core persistently busy checking on every single effing EditorApplication.update whether some main menu entries need to be installed. I kid you not. Unfortunately, I could not find a means other than Harmony to get rid of this insanity.

Just had this issue. This workaround worked for me. Worth noting: I am on Unity 2022.3.62f3 for this.