azure-functions-dotnet-worker: Regression/Breaking Change: Nullable input parameters can now cause exception

Previously, nullable input parameters would be ignored and left as null when there was no binding applicable, and the function would execute.

Since PR #1868 / 1.20, any function definition in this state will now throw a Microsoft.Azure.WebJobs.Host.FunctionInvocationException:

Function definition:

[Function(nameof(CanIGetAOhYeah))]
public async Task<HttpResponseData> Run(
    [HttpTrigger(AuthorizationLevel.Function, Route = null)] HttpRequestData requestData,
    string groan,
    CancellationToken cancellationToken)
{
}

Previous behaviour:

POST /api/CanIGetAOhYeah?groan=OH%20YEAH HTTP/1.1
HTTP/1.1 200 OK

POST /api/CanIGetAOhYeah HTTP/1.1
HTTP/1.1 200 OK

Updated behaviour:

POST /api/CanIGetAOhYeah?groan=OH%20YEAH HTTP/1.1
HTTP/1.1 200 OK

POST /api/CanIGetAOhYeah HTTP/1.1
HTTP/1.1 500 Internal Server Error
Microsoft.Azure.WebJobs.Host.FunctionInvocationException : Exception while executing function: Functions.CanIGetAOhYeah ---> Microsoft.Azure.WebJobs.Script.Workers.Rpc.RpcException : Result: Failure
Exception: Microsoft.Azure.Functions.Worker.FunctionInputConverterException: Error converting 1 input parameters for Function 'CanIGetAOhYeah': Could not populate the value for 'groan' parameter. Consider updating the parameter with a default value.
   at Microsoft.Azure.Functions.Worker.Context.Features.DefaultFunctionInputBindingFeature.BindFunctionInputAsync(FunctionContext context)
   at Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionExecutor.ExecuteAsync(FunctionContext context)
   at Microsoft.Azure.Functions.Worker.OutputBindings.OutputBindingsMiddleware.Invoke(FunctionContext context, FunctionExecutionDelegate next)
   at Microsoft.Azure.Functions.Worker.FunctionsApplication.InvokeFunctionAsync(FunctionContext context)
   at Microsoft.Azure.Functions.Worker.Handlers.InvocationHandler.InvokeAsync(InvocationRequest request)

In raising this issue, I am wanting to raise awareness of this as a breaking change; especially for anyone out there who is using the PackageReference version for Microsoft.Azure.Functions.Worker with the value 1.* 😶‍🌫️

Runtime: .NET 6 Packages:

  • Microsoft.AspNetCore.Http.Abstractions: 2.2.0
  • Microsoft.Azure.Functions.Worker: 1.20.0
  • Microsoft.Azure.Functions.Worker.ApplicationInsights: 1.0.0-preview4
  • Microsoft.Azure.Functions.Worker.Sdk: 1.16.2
  • Microsoft.Azure.Functions.Worker.Extensions.Http: 3.0.13
  • Microsoft.Net.Http.Headers: 2.2.8

About this issue

  • Original URL
  • State: closed
  • Created 8 months ago
  • Reactions: 3
  • Comments: 16 (3 by maintainers)

Commits related to this issue

Most upvoted comments

We are currently investigating this and working on a potential fix. Will keep this thread posted when a new version with the fix is available. Keep in mind that US holidays may impact how fast we can release that version of the package. Thanks for understanding.

I second this “raising awareness” issue. I’m a little disappointed that this wasn’t marked as a breaking change/major version update, as with minor version increases I would not expect such breaking behavior. Same situation, but with (multiple) .NET 7 Isolated Function Apps.

EDIT: Workaround/fix is to make the nullable parameter optional, by specifying = null.

I am also facing the issue, but in a different way. Here is my function signature:

    [Function("GetBlob")]
    public async Task<HttpResponseData> Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "{*path}")]
        HttpRequestData request,
        string path,
        FunctionContext executionContext,
        CancellationToken cancellationToken) { }

If the my function app is called without a path, I get the following exception:

Microsoft.Azure.Functions.Worker.FunctionInputConverterException: 
Error converting 1 input parameters for Function 'GetBlob': 
Could not populate the value for 'path' parameter. 
Consider updating the parameter with a default value.
  at Microsoft.Azure.Functions.Worker.Context.Features.DefaultFunctionInputBindingFeature.BindFunctionInputAsync(FunctionContext context) in D:\a\_work\1\s\src\DotNetWorker.Core\Context\Features\DefaultFunctionInputBindingFeature.cs:line 88
  at Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionExecutor.ExecuteAsync(FunctionContext context) in D:\a\_work\1\s\src\DotNetWorker.Core\Invocation\DefaultFunctionExecutor.cs:line 42
  at Microsoft.Azure.Functions.Worker.OutputBindings.OutputBindingsMiddleware.Invoke(FunctionContext context, FunctionExecutionDelegate next) in D:\a\_work\1\s\src\DotNetWorker.Core\OutputBindings\OutputBindingsMiddleware.cs:line 13
  at Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.FunctionsHttpProxyingMiddleware.Invoke(FunctionContext context, FunctionExecutionDelegate next) in D:\a\_work\1\s\extensions\Worker.Extensions.Http.AspNetCore\src\FunctionsMiddleware\FunctionsHttpProxyingMiddleware.cs:line 48
  at Microsoft.Azure.Functions.Worker.FunctionsApplication.InvokeFunctionAsync(FunctionContext context) in D:\a\_work\1\s\src\DotNetWorker.Core\FunctionsApplication.cs:line 77

Same issue with DurableTask extensions, it breaks binding like [ActivityTrigger] TaskActivityContext context.