HttpRequestMessage.CreateResponse causes stackoverflow when serializing JObject in Functions v3 runtime

This sample code was running for a long time in Function runtime v2, after platform upgrade to v3 started having stackoverflow crash in CreateResponse method:

1
2
3
4
5
6
7
8
9
10
11
[FunctionName("Function1")]
public static async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequestMessage req,
ILogger log)
{
var jsonString = @"{""Status"":""Success"",""Message"":""Function successfully executed""}";
var t = JObject.Parse(jsonString);
return req.CreateResponse(HttpStatusCode.OK, t);

}

Functions runtime v3 update is causing some infinite recursion when serializing JObject, top of the stack when overflow happens:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
InlinedCallFrame
System.ModuleHandle.ResolveTypeHandleInternal(System.Reflection.RuntimeModule, Int32, System.RuntimeTypeHandle[], System.RuntimeTypeHandle[])
System.Reflection.RuntimeModule.ResolveType(Int32, System.Type[], System.Type[])
System.Reflection.CustomAttribute.FilterCustomAttributeRecord(System.Reflection.MetadataToken, System.Reflection.MetadataImport ByRef, System.Reflection.RuntimeModule, System.Reflection.MetadataToken, System.RuntimeType, Boolean, ListBuilder`1<System.Object> ByRef, System.RuntimeType ByRef, System.IRuntimeMethodInfo ByRef, Boolean ByRef, Boolean ByRef)
System.Reflection.CustomAttribute.IsCustomAttributeDefined(System.Reflection.RuntimeModule, Int32, System.RuntimeType, Int32, Boolean)
System.Reflection.CustomAttribute.IsDefined(System.RuntimeType, System.RuntimeType, Boolean)
System.RuntimeType.IsDefined(System.Type, Boolean)
System.Runtime.Serialization.CollectionDataContract.IsCollectionOrTryCreate(System.Type, Boolean, System.Runtime.Serialization.DataContract ByRef, System.Type ByRef, Boolean)
System.Runtime.Serialization.CollectionDataContract.IsCollectionHelper(System.Type, System.Type ByRef, Boolean)
System.Runtime.Serialization.DataContract.GetNonDCTypeStableName(System.Type)
System.Runtime.Serialization.DataContract.GetStableName(System.Type, Boolean ByRef)
System.Runtime.Serialization.DataContract.GetCollectionStableName(System.Type, System.Type, System.Runtime.Serialization.CollectionDataContractAttribute ByRef)
System.Runtime.Serialization.DataContract.GetNonDCTypeStableName(System.Type)
System.Runtime.Serialization.DataContract.GetStableName(System.Type, Boolean ByRef)
System.Runtime.Serialization.DataContract.GetCollectionStableName(System.Type, System.Type, System.Runtime.Serialization.CollectionDataContractAttribute ByRef)
System.Runtime.Serialization.DataContract.GetNonDCTypeStableName(System.Type)
System.Runtime.Serialization.DataContract.GetStableName(System.Type, Boolean ByRef)
System.Runtime.Serialization.DataContract.GetCollectionStableName(System.Type, System.Type, System.Runtime.Serialization.CollectionDataContractAttribute ByRef)
System.Runtime.Serialization.DataContract.GetNonDCTypeStableName(System.Type)
System.Runtime.Serialization.DataContract.GetStableName(System.Type, Boolean ByRef)
System.Runtime.Serialization.DataContract.GetCollectionStableName(System.Type, System.Type, System.Runtime.Serialization.CollectionDataContractAttribute ByRef)
System.Runtime.Serialization.DataContract.GetNonDCTypeStableName(System.Type)
System.Runtime.Serialization.DataContract.GetStableName(System.Type, Boolean ByRef)
System.Runtime.Serialization.DataContract.GetCollectionStableName(System.Type, System.Type, System.Runtime.Serialization.CollectionDataContractAttribute ByRef)
System.Runtime.Serialization.DataContract.GetNonDCTypeStableName(System.Type)
System.Runtime.Serialization.DataContract.GetStableName(System.Type, Boolean ByRef)
System.Runtime.Serialization.DataContract.GetCollectionStableName(System.Type, System.Type,

Workaround 1:

Changed last line to return directly the json string instead of JObject, that mitigated the problem:

1
2
3
return req.CreateResponse(HttpStatusCode.OK, 
@"{""Status"":""Success"",""Message"":""Function successfully executed""}");

Workaround 2:

set “FUNCTIONS_V2_COMPATIBILITY_MODE” to “true”

HTH. By Jacky 2021-1-29