Skip to content

Backport #9984: run resolver cleanup before scheduler completion (15.x) - #10364

Open
erf1nd0r wants to merge 1 commit into
ChilliCream:main-version-15from
erf1nd0r:backport/9984-resolver-task-cleanup
Open

Backport #9984: run resolver cleanup before scheduler completion (15.x)#10364
erf1nd0r wants to merge 1 commit into
ChilliCream:main-version-15from
erf1nd0r:backport/9984-resolver-task-cleanup

Conversation

@erf1nd0r

@erf1nd0r erf1nd0r commented Sep 7, 2026

Copy link
Copy Markdown

Backport of #9984 to main-version-15. Fixes #9971 for the 15.1.x line.

On 15.1.17 and 15.1.18, ResolverTask.ExecuteAsync signals Scheduler.Complete(this) before running the resolver's cleanup tasks. When the resolver was the last running task, the scheduler completes the request and returns the OperationContext to the pool while cleanup is still pending. Any cleanup that touches the operation context, such as the CompleteUnsafeAsync registered by IResolverContext.Clone(), then throws ObjectDisposedException ("The specified object was not initialized and is no longer usable"). The faulted task is never awaited, so it surfaces as an UnobservedTaskException on the finalizer thread.

The fix on main reorders the finally block so cleanup runs first and Scheduler.Complete plus the pool return happen in a nested finally. This is a cherry-pick of 6e5b640 with no API changes. The only adjustment is in the test: this branch uses xunit v2, so TestContext.Current.CancellationToken was replaced with CancellationToken.None.

Verified locally on this branch (net9.0): the backported test ResolveAsync_Should_NotFaultClonedContext_When_EntitiesResolvedConcurrently fails within ~650 ms on the unpatched main-version-15 source with a list of ObjectDisposedExceptions, and passes with the fix applied.

We hit this in production on 15.1.17 through the Relay node(id:) field, which clones the resolver context in NodeFieldResolvers. Any @refetchable Relay fragment on a Node type triggers it, so it is not limited to Apollo Federation _entities as described in #9971. Responses stay correct, but the exception is logged on every occurrence. Upgrading to 16.x is not an option for us yet because a shared internal package pins HotChocolate to [15.1.14, 16.0.0).

…eam#9984)

(cherry picked from commit 6e5b640)

Backport to main-version-15: the test project on this branch uses xunit v2, so
TestContext.Current.CancellationToken was replaced with CancellationToken.None.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants