Open stuartf-aida opened 2 weeks ago
This is perfect, thank you! Will add this to todo list :)
edit: @stuartf-aida any chance you have a minimal repro I can use to investigate the issue? Or other info on the type of function that is failing with this error i.e. is it a dotnet-isolated app? v4? .net 6 or .net 8? what kind of trigger binding? etc.
@liliankasem It's dotnet isolated, v8. Http trigger binding.
We've shifted our code now to use an alternative, based on the workaround for the previous issue where I originally posted. That seems (so far) to have solved this, but it's hard to say. We don't (and didn't) have a situation that reliably caused this to happen - most invocations would not error. We can use the same payload on the http trigger such that the same code runs and we've not successfully reproduced the issue.
The function doesn't do very much.
It uses Azure.Security.KeyVault.Secrets (4.7.0) to grab a secret from the keyvault, Environment.GetEnvironmentVariable to get an environment variable and Azure.Storage.Queues (12.20.1) to put an entry on a queue
and along the way a bit of string manipulation
Thanks very much for your keen attention on these issues!
Okay so it looks like we have a fun two part bug.
The first part is in the host. The DefaultHttpProxyService
has this code which does not take into account cancellation (ForwarderError.RequestCanceled
). Whether cancellation is handled or not by the worker/customer code, we will always get this error message when an invocation is cancelled:
System.InvalidOperationException : Failed to proxy request with ForwarderError: RequestCanceled
There is also a bug in the AspNetCore worker extension which breaks the cancellation behaviour. In the DefaultHttpCoordinator
, we pass in the cancellation token when we create the ContextReference:
var contextRef = _contextReferenceList.GetOrAdd(invocationId, static id => new ContextReference(id));
contextRef.SetCancellationToken(context.CancellationToken);
contextRef.FunctionContextValueSource.SetResult(context);
As a result, when a function invocation is cancelled, we cancel that same cts that is being used by ContextReference:
cancellationTokenSource?.Cancel();
So, we end up with a disposed HttpContext when we try to handle the invocation result:
ActionContext actionContext = new ActionContext(httpContext, httpContext.GetRouteData(), new ActionDescriptor());
await actionResult.ExecuteResultAsync(actionContext);
This is where the ObjectDisposedExecpetion comes from:
Exception: System.ObjectDisposedException: Request has finished and HttpContext disposed.
Object name: 'HttpContext'.
at Microsoft.AspNetCore.Http.DefaultHttpContext.ThrowContextDisposed()
at Microsoft.AspNetCore.Http.DefaultHttpContext.get_Features()
at Microsoft.AspNetCore.Routing.RoutingHttpContextExtensions.GetRouteData(HttpContext httpContext)
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 54
at Microsoft.Azure.Functions.Worker.FunctionsApplication.InvokeFunctionAsync(FunctionContext context) in D:\a\_work\1\s\src\DotNetWorker.Core\FunctionsApplication.cs:line 89
Stack: at Microsoft.AspNetCore.Http.DefaultHttpContext.ThrowContextDisposed()
at Microsoft.AspNetCore.Http.DefaultHttpContext.get_Features()
at Microsoft.AspNetCore.Routing.RoutingHttpContextExtensions.GetRouteData(HttpContext httpContext)
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 54
at Microsoft.Azure.Functions.Worker.FunctionsApplication.InvokeFunctionAsync(FunctionContext context) in D:\a\_work\1\s\src\DotNetWorker.Core\FunctionsApplication.cs:line 89
I'll speak with the team and discuss how we want to handle these issues.
DefaultHttpProxyService
ObjectDisposedException
bugHi I am facing this too. I have a function app on node.js 20.0 LTS stack. Basically, I developed multiple http trigger functions within a function app, tested them via postman, deployed it on azure function app. The moment I run any of them, I see the following error
Hi @liliankasem is there an ETA on when this is going to be fixed? or is there a workaround for this? This is impacting our development efforts. Thanks.
We have impact as well...
No ETA at the moment, but we are working on it.
However, there should not be any real impact as this is mostly noise/badly handled exception on our end. If your function invocation is getting cancelled it is likely due to a client disconnect or something else shutting things down. If you handle the cancellation token in your code, your invocation should still run till completion even if it fails.
If there is real production impact, please open a customer support issue via the Azure portal so we can investigate further. Thanks!
Proxy not forwarding cancellation token correctly to function app
Canada Central example @pmerineau first reported https://github.com/Azure/azure-functions-dotnet-worker/issues/2417#issuecomment-2455793340
North Europe example @stuartf-aida first reported https://github.com/Azure/azure-functions-dotnet-worker/issues/2417#issuecomment-2455857336
As mentioned by @liliankasem
I hope this is what you need, Lilian!