CosmosDbOutput of an Azure Function reports "Value cannot be null. Parameter ('document')"

Viewed 445

I have recently moved to Azure Functions with .NET 5 (dotnet-isolated). I experienced an exception using an output binding to CosmosDb that was hard to debug. I'm going to post the answer below for further reference.

First, the function was straight forward but with a rather complex return type.

[Function(nameof(StationStore))]
[CosmosDBOutput(
    databaseName: "%Database%", 
    collectionName: "%Collection%", 
    CreateIfNotExists = true,
    ConnectionStringSetting = "CosmosDbConnectionString")]
 public CosmosModel Run(
     [ServiceBusTrigger("%Queue_Storage%", Connection = "ServiceBusConnection")]
     StoreModel metaModel,
      // Trigger not relevant for question
      FunctionContext context)
 {
   // code omitted, doesn't matter for question
   return new CosmosModel();
 }

I got this exception after code execution, so not stack trace and no way to set a breakpoint.

System.Private.CoreLib: Exception while executing function: Functions.StationStore. Microsoft.Azure.DocumentDB.Core: Value cannot be null. (Parameter 'document').

Because the return parameter was properly set the message seems very strange.

1 Answers

To test the behavior I used the JsonSerializer directly. Return type is now string and the last line of code looks like this (with model is again CosmosModel):

return JsonSerializer.Serialize(model);

Now I got an System.InvalidOperationException that says in the details:

'The JSON property name for 'MyNameSpace.CosmosModel.Name' collides with another property.'

There are three conclusions:

  1. The serializer uses System.Text.Json
  2. If an error occurs the serializer's exception is being catched and the object it returns is set to null
  3. The CosmosDbOutput binder throws the exception that says something like "null is not allowed"

The third step prevents the execution engine from revealing the details and let you in the dark.

I fixed the serializer error and rewrote the function to work with the original object and it works as expected now.

Addendum: "dotnet-isolated" function binders use System.Text.Json only partially, it's not the case for QueueOutput for example. I expect that this will change in near future, but it makes working with isolated functions a lot harder than it should be.

Related