Ok. I have just run into this same problem.
In my case, the issue was because i was loading an assembly from a byte array (i'm using a plugin model, so this is fairly common use) and was deserializing an object but it wouldn't cast with the same message as the original question.
At first i thought it was just because of the serializer and dll versioning and such...so i wrote my own serializer and ran into the same issue again.
The issue really came from type creation. In my deserialization routines i was using the familiar Type.GetType(string) method and passing an AssemblyQualifiedName, which does work and for all types that reside outside of mscorlib, it's required.
Well, turns out that GetType does not walk the list of loaded assemblies to try and find a match but leaves it up to the fusion resolver.
This means that any type that exists in an assembly that was loaded in any context other than 'Load' (aka 'Default' in the exception message) is not found and GetType attempts to load the assembly normally.
In my case, this behavior caused 2 instances of the assembly to be loaded in the appdomain: on from my byte array, and the other from disk as found by fusion.
I solved this problem by enumerating the loaded assemblies in my appdomain, looking for a matching assembly name (parsed from my AssemblyQualifiedName). Once found, i created my type (minus the assembly info) using that specific assembly (Assembly.GetType(String)).
Here's the code that allowed me to overcome this issue:
Dim ot As System.Type
Dim tname = "MyType"
Dim aname = "MyPlugin"
'// The following lambda expression returns only assemblies that match my assembly name
'// Your assembly name could be a fully qualified name or just the simple assembly name
'// I chose to use the simple name so that i didn't have to store unnecessary data and because i didn't want version specific info
Dim asms = AppDomain.CurrentDomain.GetAssemblies().Where(Function(__) __.GetName.Name.Equals(aname))
'If there is only one assembly loaded...use it
If asms.Count = 1 Then
ot = asms(0).GetType(tname)
'// If there are multiple assemblies loaded (with the same name), i'm picking the one that is loaded from disk, if such is available, otherwise default back to the first one that was loaded into the appdomain
'// If you do have multiple assemblies loaded, it's because you (or .NET) has loaded them in different contexts. You might need to adjust for which context you want. I suppose you could pass the desired context in as a parameter and look for it
ElseIf asms.Count > 1 Then
Dim asm = asms.FirstOrDefault(Function(__) Not String.IsNullOrEmpty(__.Location))
If asm IsNot Nothing Then
ot = asm.GetType(tname)
Else
ot = asms(0).GetType(tname)
End If
Else
'// not yet loaded...use default type resolution from Type.GetType
ot = Type.GetType(tname & "," & aname)
End If
Dim obj
'// Note that the method here is using the already resolved System.Type from above.
'// This is important because it causes Activator to create an instance from the assembly
'// that we really want and not one from fusion's resolver.
obj = Activator.CreateInstance(ot)
Hopefully this is helpful to someone else.
-Eriq