Thursday, September 06, 2007

XLANG/s error 10034 FileLoadException at _GetTypeByName, Issue and Resolution

(For those who want the abstract, see `The Solution` below.)

After performing a migration of a BizTalk 2004 project to BizTalk 2006 and running some unit tests, I ran into a very frustrating and at first misleading error in the application event log.

Source: XLANG/s
Event ID: 10034
Type: Error
Category: None

Uncaught exception (see the 'inner exception' below) has suspended an instance of service ' Bulloch.ProcessTrs(5146e3cd-3d88-4845-0795-4ccd1196bbe3)'.
The service instance will remain suspended until administratively resumed or terminated.
If resumed the instance will continue from its last persisted state and may re-throw the same unexpected exception.
InstanceId: 29059449-1b02-4e27-9b09-520ec69520a7
Shape name: Receive Trs File
ShapeId: f8763ddd-f0a3-41a9-9aee-4d13bc541cfa
Exception thrown from: segment 1, progress 3
Inner exception: The given assembly name or codebase was invalid. (Exception from HRESULT: 0x80131047)
Exception type: FileLoadException
Source: mscorlib
Target Site: Void* _GetTypeByName(System.String, Boolean, Boolean, Boolean, System.Threading.StackCrawlMark ByRef, Boolean)
The following is a stack trace that identifies the location where the exception occured

   at System.RuntimeTypeHandle._GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, Boolean loadTypeFromPartialName)
   at System.RuntimeTypeHandle.GetTypeByName (String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark)
   at System.RuntimeType.PrivateGetType(String typeName, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark)
   at System.Type.GetType(String typeName)
   at Microsoft.XLANGs.Core.XMessage._verifyPublisherSchema()
   at Microsoft.XLANGs.Core.XMessage.FetchProperties()
   at Microsoft.BizTalk.XLANGs.BTXEngine.BTXPortBase.ReceiveMessage (Int32 iOperation, Envelope env, XLANGMessage msg, Correlation[] initCorrelations, Context cxt, Segment s)
   at Bulloch.ProcessTrx.segment1(StopConditions stopOn)
   at Microsoft.XLANGs.Core.SegmentScheduler.RunASegment (Segment s, StopConditions stopCond, Exception& exp)

My first thought was (due to the FileLoadException) was that an assembly couldn't be found and gave myself a crash course in debugging .NET assembly loading (the Fusion Log viewer is very useful. See a good explanation here).  Sadly, this did not help. 

After fearing a breaking change in the BizTalk engine (I was using the R2 Beta), I started again from first principles, first trying to trace the exception stack using Lutz Roeder's .NET Reflector.  This triggered the first critical link: the orchestration is failing on the Receive shape, confirmed by the stack trace referring to the method ReceiveMessage() in the XLANG/s engine.  I knew the subscription was fine, as it triggered the orchestration, but it seemed to have difficulty loading the message instance itself.  The message body looked fine and so I started to look at the message context.  Looking at the property SchemaStrongName, I looked at the description:

"SchemaStrongName" is not a promoted property.  Such Properties can be used for message tracking and can be referenced by components (e.g. from Orchestration), but they are not used for routing.

Working on this lead, I looked at the strong name of the schema that was deployed in the Schema node of the BizTalk application.  Sure enough, it didn't match.  Consequently, the orchestration subscription kicked off a new orchestration instance, but when the engine tried to load the message instance by type name (ie its strong name) it failed.

First of all, I had been using a custom file disassembler to build the original message and in hindsight, this should have been one of the first places I looked.  In the custom pipeline component, I was manually setting the value of SchemaStrongName.  The assembly's strong name changed when I built the new project because I started to use a new strong name key, thus changing the PublicKeyToken part of the strong name.

Second of all, and perhaps rather mysterious, is that the original code (which had been functioning in BizTalk 2004) used a different format for the SchemaStrongName string.  Strong names for schemas should be in this format:
Fully.Qualified.SchemaName, Fully.Qualified.AssemblyName, Version=x.x.x.x, Culture=neutral, PublicKeyToken=XXXXXXXXXXXXXXXXXX
whereas the original code simply used the format
Fully.Qualified.AssemblyName, Version= x.x.x.x, Culture=neutral, PublicKeyToken=XXXXXXXXXXXXXXXXXX

Beats me as to why it worked in BTS 2004, but the good news is I found the solution.

The Solution

If using custom file disassemblers where you manually assign the SchemaStrongName property, ensure it always matches the complete schema strong name of the deployed schema as shown in the BizTalk Administration Console, otherwise you will get an XLANGs error indicating a FileLoadException.

No comments: