diff --git a/docs/versionhistory.rst b/docs/versionhistory.rst
index fb81ec05..bdf0922a 100644
--- a/docs/versionhistory.rst
+++ b/docs/versionhistory.rst
@@ -12,6 +12,9 @@ This library adheres to `Semantic Versioning 2.0 `_.
when cancelling a task in a TaskGroup created with the ``start()`` method before
the first checkpoint is reached after calling ``task_status.started()``
(`#706 `_; PR by Dominik Schwabe)
+- Fixed cancellation delivery on asyncio incrementing the wrong cancel scope's
+ cancellation counter when cascading a cancel operation to a child scope, thus failing
+ to uncancel the host task (`#716 `_)
- Fixed erroneous ``TypedAttributeLookupError`` if a typed attribute getter raises
``KeyError``
- Fixed the asyncio backend not respecting the ``PYTHONASYNCIODEBUG`` environment
diff --git a/src/anyio/_backends/_asyncio.py b/src/anyio/_backends/_asyncio.py
index 860c9999..ecd865a7 100644
--- a/src/anyio/_backends/_asyncio.py
+++ b/src/anyio/_backends/_asyncio.py
@@ -488,7 +488,7 @@ def _deliver_cancellation(self, origin: CancelScope) -> bool:
if task is not current and (task is self._host_task or _task_started(task)):
waiter = task._fut_waiter # type: ignore[attr-defined]
if not isinstance(waiter, asyncio.Future) or not waiter.done():
- self._cancel_calls += 1
+ origin._cancel_calls += 1
if sys.version_info >= (3, 9):
task.cancel(f"Cancelled by cancel scope {id(origin):x}")
else:
diff --git a/tests/test_taskgroups.py b/tests/test_taskgroups.py
index d54115f4..da84f656 100644
--- a/tests/test_taskgroups.py
+++ b/tests/test_taskgroups.py
@@ -458,6 +458,19 @@ async def test_cancel_before_entering_scope() -> None:
pytest.fail("execution should not reach this point")
+@pytest.mark.xfail(
+ sys.version_info < (3, 11), reason="Requires asyncio.Task.cancelling()"
+)
+@pytest.mark.parametrize("anyio_backend", ["asyncio"])
+async def test_cancel_counter_nested_scopes() -> None:
+ with CancelScope() as root_scope:
+ with CancelScope():
+ root_scope.cancel()
+ await sleep(0.5)
+
+ assert not cast(asyncio.Task, asyncio.current_task()).cancelling()
+
+
async def test_exception_group_children() -> None:
with pytest.raises(BaseExceptionGroup) as exc:
async with create_task_group() as tg: