fix(pydantic-ai): Use first-class hooks when available #5947
5 issues
Medium
are_request_hooks_available incorrectly set to True when Hooks import fails - `sentry_sdk/integrations/pydantic_ai/__init__.py:66`
On line 66, when the Hooks import fails (meaning hooks are NOT available), the code sets are_request_hooks_available = True. This is logically incorrect - it should be False since hooks are unavailable. While the class attribute defaults to True (line 32), the exception handler should flip it to False. This causes unnecessary metadata initialization ({"_sentry_span": None}) in agent_run.py even when hooks aren't being used, which is wasteful and potentially confusing for debugging.
Span entered but never exited when ctx.metadata is not a dict - `sentry_sdk/integrations/pydantic_ai/__init__.py:91`
In on_request, span.__enter__() is called unconditionally at line 91, but the span is only stored in metadata if run_context_metadata is a dict (lines 88-89). When metadata is not a dict, on_response returns early at line 103-104 without calling span.__exit__(). This causes a span leak - the span will remain open indefinitely, potentially corrupting the span hierarchy for subsequent operations.
Also found at:
sentry_sdk/integrations/pydantic_ai/__init__.py:106
are_request_hooks_available incorrectly set to True when hooks are unavailable - `sentry_sdk/integrations/pydantic_ai/__init__.py:66`
At line 66, when ImportError is raised (meaning pydantic_ai.capabilities.Hooks is not available), the code sets PydanticAIIntegration.are_request_hooks_available = True. This is incorrect - it should be False since the hooks mechanism is not available. This causes the agent_run wrapper to incorrectly add metadata to kwargs when using the fallback patch approach.
Agent created before sentry_init() bypasses capability hooks injection - `tests/integrations/pydantic_ai/test_pydantic_ai.py:654`
In test_without_pii_tools, the test_agent is instantiated via get_test_agent() on line 654 before sentry_init() is called on line 661. The PydanticAI integration patches Agent.__init__ during setup_once() to inject capability hooks for request/response tracking. Since the agent is created before this patch is applied, it won't have the hooks injected, potentially causing incomplete instrumentation or test failures on newer pydantic-ai versions that use the Hooks capability.
Low
Falsy check on metadata may overwrite user's empty dict - `sentry_sdk/integrations/pydantic_ai/patches/agent_run.py:113-114`
The condition if not metadata: treats both None and empty dict {} the same way. If a user explicitly passes metadata={}, the code overwrites it with {"_sentry_span": None} instead of preserving their (empty) dict. While this edge case is unlikely in practice, using if metadata is None: would be more precise and avoid potential confusion or data loss when users intend to pass an empty metadata dict that they plan to populate later.
4 skills analyzed
| Skill | Findings | Duration | Cost |
|---|---|---|---|
| code-review | 2 | 6m 7s | $1.49 |
| find-bugs | 3 | 7m 32s | $2.72 |
| skill-scanner | 0 | 5m 6s | $0.92 |
| security-review | 0 | 3m 11s | $0.89 |
Duration: 21m 56s · Tokens: 3.6M in / 55.8k out · Cost: $6.03 (+extraction: $0.00, +merge: $0.00, +fix_gate: $0.01, +dedup: $0.01)