Skip to content

fix(dedupe): Avoid retaining strong references to user exceptions#6103

Closed
ericapisani wants to merge 1 commit intomasterfrom
ep/py-2381-investigate-1mw
Closed

fix(dedupe): Avoid retaining strong references to user exceptions#6103
ericapisani wants to merge 1 commit intomasterfrom
ep/py-2381-investigate-1mw

Conversation

@ericapisani
Copy link
Copy Markdown
Member

@ericapisani ericapisani commented Apr 20, 2026

Avoid holding a strong reference to the last-seen exception in
DedupeIntegration.

When weakref.ref(exc) failed (some builtin exception types can't be
weak-referenced), the integration previously stored the exception
instance itself as a fallback on its context var. That meant the
exception — along with its traceback frames, locals, and any user
objects captured on the frame — stayed alive until the next exception
replaced it, which showed up as unexpected memory retention in
long-running processes.

Fall back to a (type, hash(args)) fingerprint instead. Dedupe can
still recognize a repeat of the same exception to suppress duplicates,
but nothing about the original instance is retained. exc.args hashing
is guarded (repr() fallback, then 0) so unhashable args won't break
dedupe.

Refs PY-2381
Fixes #6094

DedupeIntegration stored the original exception instance as a fallback
when `weakref.ref(exc)` failed (e.g. for builtin exception types). That
meant a reference to every such exception lived on the context var
until the next exception replaced it, potentially pinning large
traceback frames, locals, and user objects in memory.

Instead, fall back to a `(type, hash(args))` fingerprint so dedupe can
still suppress duplicates without keeping the exception alive.

Refs PY-2381
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@linear-code
Copy link
Copy Markdown

linear-code bot commented Apr 20, 2026

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 20, 2026

Semver Impact of This PR

🟢 Patch (bug fixes)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


New Features ✨

  • (ci) Cancel in-progress PR workflows on new commit push by joshuarli in #5994
  • Add db.driver.name spans to database integrations by ericapisani in #6082

Bug Fixes 🐛

  • (dedupe) Avoid retaining strong references to user exceptions by ericapisani in #6103
  • (google_genai) Redact binary data in inline_data and fix multi-part message extraction by ericapisani in #5977
  • (grpc) Add isolation_scope to async server interceptor by robinvd in #5940
  • (profiler) Stop nulling buffer on teardown by ericapisani in #6075

Internal Changes 🔧

  • (celery) Remove unused NoOpMgr from utils by sentrivana in #6078
  • (ci) Update outdated pinned action version comments by JoshuaMoelans in #6088
  • (pydantic-ai) Remove dead Model.request patch by alexander-alderman-webb in #5956
  • (tests) Replace deprecated enable_tracingwith traces_sample_rate by sentrivana in #6077
  • Set explicit base-branch for codecov action by ericapisani in #5992

🤖 This preview updates automatically when you update the PR.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 20, 2026

Codecov Results 📊

142 passed | Total: 142 | Pass Rate: 100% | Execution Time: 21.61s

All tests are passing successfully.

❌ Patch coverage is 58.82%. Project has 14160 uncovered lines.

Files with missing lines (1)
File Patch % Lines
dedupe.py 73.58% ⚠️ 14 Missing and 4 partials

Generated by Codecov Action

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.

Memory leak: DedupeIntegration pins exception tracebacks in asyncio apps

1 participant