System.InvalidProgramException: Common Language Runtime detected an invalid program
I just spent a while fighting an exception that was being thrown from within a .NET runtime-generated assembly—specifically from Microsoft.
tl;dr
The object being serialized included this method:
public static bool ShouldSerializeFoobarProp() => false;
Eliminating the static
declaration made the problem go away[1].
The full story
I’ve got a class defined which can be populated from and/or serialized to XML. It uses a bunch of [XmlElement("foobar")]
annotations, and is 95% just used as a data structure. It gets serialized to XML thusly:
XmlSerializer s = new XmlSerializer(typeof(MyFoobarClass));
using (StringWriter w = new StringWriter())
{
XmlSerializerNamespaces xmlnsEmpty = new XmlSerializerNamespaces();
xmlnsEmpty.Add("", "");
try
{
s.Serialize(w, myFoobarObject, xmlnsEmpty);
However, there are a few public properties of the class that, while useful elsewhere in the code, don’t necessarily make sense when serializing to XML. I employed the ShouldSerialize{PropertyName}
pattern[2] to selectively serialize certain elements and attributes only when useful, and never serialize another property.[1]
That all worked fine. At some point, I worked through a bunch of code analysis hints, one of which correctly pointed out that CA1822 Member ShouldSerialize{Foobar} does not access instance data and can be marked as static (Shared in VisualBasic). I didn’t have a unit test for this (tsk, tsk!), so everything looked fine. This serialization doesn’t even run during most normal use of the software, so no red flags were raised for quite a while. Thankfully, before these changes shipped, I did exercise this code path, and was greeted with System.InvalidProgramException: Common Language Runtime detected an invalid program thrown from the call to s.Serialize(...)
.
Search results for this exception pointed me to corrupt builds, x86/x64 mismatch, corrupt Visual Studio session data, corrupt .NET runtime installations, etc, none of which was helpful in this case. Eventually I found a StackOverflow answer from Youssef Moussaoui that talked about XmlSerializer changes in .NET 4.5.
I tried changing the .NET targeted runtime for my projects to no avail, but he also included an app.config toggle to force legacy
behavior. When I tried that, I got a new exception! This one actually occurred earlier in the execution—when attempting to construct the serializer—but more importantly made a reference to my ShouldSerizlier{Foobar}
static method:
System.InvalidOperationException: ‘Unable to generate a temporary class (result=1).
error CS0176: Member ‘MyFoobarClass.ShouldSerializeFoobarProp()’ cannot be accessed with an instance reference; qualify it with a type name instead’
That was enough to point me to that method, which I saw was marked static. After eliminating the static keyword (and then silencing the resulting code analysis hint), voilĂ , everything was happy once again!
[1] This, of course, turns out to not be the right way to universally ignore an element for serialization. The [XmlIgnore]
annotation/attribute is the much more obvious and easy way to accomplish this.
[2] I’m sure I learned about the ShouldSerialize{PropertyName}
functionality on StackOverflow, specific to XmlSerializer, but I wasn’t able to easily find official documentation of the feature in that context when writing this post. This reference to winforms was the best I could do.