Skip to content

fix(tasks): clean up execution_spans on async CancelledError - #7361

Open
devtechedge wants to merge 1 commit into
crewAIInc:mainfrom
devtechedge:fix/cancelled-task-execution-spans
Open

devtechedge wants to merge 1 commit into
crewAIInc:mainfrom
devtechedge:fix/cancelled-task-execution-spans

Conversation

@devtechedge

@devtechedge devtechedge commented Sep 9, 2026

Copy link
Copy Markdown

Summary

Fixes #7351.

When an async task is cancelled after TaskStartedEvent, asyncio.CancelledError was skipping the except Exception path in _aexecute_core(). That meant no terminal event was emitted, so EventListener.execution_spans kept a strong reference to the Task (and through it the Agent / Crew graph).

This change catches CancelledError explicitly, emits TaskFailedEvent so the existing listener can pop the span entry and close telemetry the same way ordinary failures do, then re-raises to preserve cancellation semantics.

Changes

  • lib/crewai/src/crewai/task.py: handle asyncio.CancelledError before except Exception in _aexecute_core()
  • lib/crewai/tests/telemetry/test_task_cancellation_span_cleanup.py: regression tests for span cleanup and TaskFailedEvent emission on cancel

Why TaskFailedEvent

Reusing TaskFailedEvent is the smallest behavior change. The listener already pops execution_spans and routes failures through task_failed. A dedicated cancellation event would be nicer for telemetry consumers later, but it is not required to close the leak.

Test plan

  • Added async regression covering repeated cancellations + weakref GC
  • Added producer-level check that CancelledError emits TaskFailedEvent
  • CI: uv run pytest lib/crewai/tests/telemetry/test_task_cancellation_span_cleanup.py -x -q

Notes for maintainers

Happy to adjust if you would rather introduce a dedicated cancellation event instead of reusing TaskFailedEvent.

I do not have permission to apply labels here - please add llm-generated when you can (required by the contributing guide).

Thanks for reviewing.

Emit TaskFailedEvent when _aexecute_core is cancelled so EventListener can pop the span entry and release retained task graphs. Adds regression coverage for issue crewAIInc#7351.
@devtechedge

Copy link
Copy Markdown
Author

Quick note for maintainers: I do not have permission to apply labels on this repo. Please add llm-generated when you get a chance - required by the contributing guide. Thanks.

@coderabbitai

coderabbitai Bot commented Sep 9, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: e3eefe62-1f32-4800-8204-0490b18cfada

📥 Commits

Reviewing files that changed from the base of the PR and between 4ed4aba and 1efb337.

📒 Files selected for processing (2)
  • lib/crewai/src/crewai/task.py
  • lib/crewai/tests/telemetry/test_task_cancellation_span_cleanup.py

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

The task execution path now handles asyncio.CancelledError as a terminal failure, records completion time, emits TaskFailedEvent, and re-raises. Telemetry tests verify span cleanup, object collection, and event details.

Changes

Async cancellation handling

Layer / File(s) Summary
Cancellation terminal event handling
lib/crewai/src/crewai/task.py
_aexecute_core records end_time, emits TaskFailedEvent for CancelledError, and re-raises the cancellation.
Cancellation cleanup regression tests
lib/crewai/tests/telemetry/test_task_cancellation_span_cleanup.py
Tests verify that cancelled tasks leave no execution_spans entries, allow related objects to be collected, and emit one TaskFailedEvent with the expected error type.

Suggested reviewers: joaomdmoura

Priority: ➖ Normal

Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to 1efb3

Cancelled async tasks now emit a terminal failure event before cancellation propagates, allowing telemetry spans and related task objects to be cleaned up. The targeted cleanup and event behavior are covered by regression tests, with no remaining merge-blocking risk identified.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 62.50% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 8 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes satisfy issue #7351 by handling CancelledError explicitly, emitting TaskFailedEvent, re-raising cancellation, removing execution_spans entries through the existing listener, and testing ob…
Out of Scope Changes check ✅ Passed The production change and regression tests are directly related to async cancellation cleanup and the requirements in issue #7351. No unrelated code changes are identified.
Title check ✅ Passed The title clearly identifies the async CancelledError cleanup fix and matches the main change.
Description check ✅ Passed The description explains the issue, solution, design choice, affected files, and regression tests. It includes the linked issue and verification details, although some content uses headings that diffe…
  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Cancelled async tasks remain in execution_spans and retain task graphs

1 participant