Skip to content

SqlPersistenceTask: An unhandled exception occurred: Could not find assembly 'NServiceBus.Persistence.Sql, Version=9.0.0.0#1898

Closed
danielmarbach wants to merge 4 commits intomasterfrom
script-builder-loading
Closed

SqlPersistenceTask: An unhandled exception occurred: Could not find assembly 'NServiceBus.Persistence.Sql, Version=9.0.0.0#1898
danielmarbach wants to merge 4 commits intomasterfrom
script-builder-loading

Conversation

@danielmarbach
Copy link
Contributor

@danielmarbach danielmarbach commented Jan 12, 2026

The issue was that the MetadataLoadContext needed to resolve referenced assemblies (like NServiceBus.Persistence.Sql) when reading custom attributes, but the MSBuild task runs AfterTargets="AfterCompile" using the intermediate assembly from the obj/ folder, where dependencies might not be copied yet.

The fix passes the @(ReferencePath) item group from MSBuild to the script generator, which contains the full paths to all referenced assemblies. These are then included in the PathAssemblyResolver so the MetadataLoadContext can resolve them.

2>: Error  : SqlPersistenceTask: An unhandled exception occurred:
Exception:
Could not find assembly 'NServiceBus.Persistence.Sql, Version=9.0.0.0, Culture=neutral, PublicKeyToken=9fc386479f8a226c'. Either explicitly load this assembly using a method such as LoadFromAssemblyPath() or use a MetadataAssemblyResolver that returns a valid assembly.
StackTrace:
   at System.Reflection.TypeLoading.Ecma.EcmaResolver.ResolveAssembly(AssemblyReferenceHandle handle, EcmaModule module)
   at System.Reflection.TypeLoading.Ecma.EcmaResolver.ComputeTypeRefResolution(TypeReferenceHandle handle, EcmaModule module)
   at System.Reflection.TypeLoading.Ecma.EcmaResolver.<>c.<.cctor>b__15_1(EntityHandle h, EcmaModule m)
   at System.Reflection.TypeLoading.Ecma.MetadataTable`2.GetOrAdd(EntityHandle handle, C context, Func`3 factory)
   at System.Reflection.TypeLoading.Ecma.EcmaResolver.ResolveTypeRef(TypeReferenceHandle handle, EcmaModule module)
   at System.Reflection.TypeLoading.Ecma.EcmaResolver.ResolveTypeDefRefOrSpec(EntityHandle handle, EcmaModule module, TypeContext& typeContext)
   at System.Reflection.TypeLoading.Ecma.EcmaCustomAttributeData.ComputeAttributeType()
   at System.Reflection.TypeLoading.RoCustomAttributeData.get_AttributeType()
   at SettingsAttributeReader.<>c.<Read>b__0_0(CustomAttributeData x) in /_/src/ScriptBuilder/AttributeReading/SettingsAttributeReader.cs:line 14
   at System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable`1 source, Func`2 predicate, Boolean& found)
   at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
   at SettingsAttributeReader.Read(Assembly assembly) in /_/src/ScriptBuilder/AttributeReading/SettingsAttributeReader.cs:line 13
   at ScriptGenerator.Generate() in /_/src/ScriptBuilder/ScriptGenerator.cs:line 49
   at ScriptGenerator.Generate(String assemblyPath, String targetDirectory, Action`2 logError, Func`2 promotionPathFinder) in /_/src/ScriptBuilder/ScriptGenerator.cs:line 24
   at InnerTask.Execute() in /_/src/ScriptBuilderTask/InnerTask.cs:line 24
   at NServiceBus.Persistence.Sql.SqlPersistenceScriptBuilderTask.Execute() in /_/src/ScriptBuilderTask/SqlPersistenceScriptBuilderTask.cs:line 42
Source:
System.Reflection.MetadataLoadContext

@danielmarbach danielmarbach changed the title script-builder-loading SqlPersistenceTask: An unhandled exception occurred: Could not find assembly 'NServiceBus.Persistence.Sql, Version=9.0.0.0 Jan 12, 2026
@danielmarbach
Copy link
Contributor Author

Local build verification of latest commit

image image

@danielmarbach
Copy link
Contributor Author

@bording Given this is not an area I'm super knowledgeable in, I'd appreciate your review

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes an issue where the MSBuild task failed to resolve referenced assemblies when using MetadataLoadContext to read custom attributes. The task runs after compilation using the intermediate assembly from the obj/ folder, where dependencies aren't yet copied. The solution passes the @(ReferencePath) item group from MSBuild, which contains full paths to all referenced assemblies, ensuring the MetadataLoadContext can resolve them properly.

Changes:

  • Added ReferencePath parameter to the MSBuild task and targets file to pass referenced assembly paths
  • Modified ScriptGenerator to accept and use reference paths when creating the PathAssemblyResolver
  • Added comprehensive tests to verify the fix works in isolated assembly scenarios

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
SqlPersistenceScriptBuilderTask.cs Added ReferencePath property and passes it to InnerTask
NServiceBus.Persistence.Sql.targets Passes @(ReferencePath) from MSBuild to the task
InnerTask.cs Accepts referencePaths parameter and forwards to ScriptGenerator
ScriptGenerator.cs Implements CollectAssemblyFiles method to include reference paths in assembly resolution
SettingsAttributeReader.cs Minor code style modernization (collection expressions)
InnerTaskTests.cs Added tests for isolated assembly scenarios with and without reference paths
InnerTaskTests approval file Renamed to match updated test name
APIApprovals.Approve.approved.txt Updated to reflect new public API surface

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@danielmarbach

This comment was marked as resolved.

This comment was marked as resolved.

…nerator (#1899)

* Initial plan

* Refactor foreach loops to use explicit .Where() filtering

Co-authored-by: danielmarbach <174258+danielmarbach@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: danielmarbach <174258+danielmarbach@users.noreply.github.com>
@DavidBoike
Copy link
Member

DavidBoike commented Jan 12, 2026

@DavidBoike DavidBoike closed this Jan 12, 2026
@DavidBoike DavidBoike deleted the script-builder-loading branch January 12, 2026 22:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants