dheerajturaga commented on code in PR #68039:
URL: https://github.com/apache/airflow/pull/68039#discussion_r3360020080


##########
airflow-core/src/airflow/api_fastapi/execution_api/app.py:
##########
@@ -253,9 +252,16 @@ async def _extract_w3c_trace_context(
     token = otel_context.attach(ctx)
     try:
         yield
-    finally:
-        with contextlib.suppress(Exception):
-            otel_context.detach(token)
+    except GeneratorExit:
+        # The dependency generator was force-closed (client disconnect / 
request
+        # cancellation): the finalizer runs in a different asyncio Task — and 
thus a
+        # different contextvars.Context — than attach did, so detaching the 
token would
+        # raise "Token was created in a different Context" (which OTel logs at 
ERROR
+        # before any suppression here could see it). The attached Context is 
being
+        # discarded with the dying task, so detaching is unnecessary; skip it 
and re-raise.
+        raise
+    else:
+        otel_context.detach(token)

Review Comment:
   Great catch — you're right, and it was a regression. FastAPI finalizes this 
dependency by `athrow`-ing the route exception into the generator at the 
`yield` (confirmed via `_solve_generator` -> `asynccontextmanager` -> 
`AsyncExitStack`), which took neither branch, so detach was skipped on a 
same-task path where it both should and would have succeeded — leaking the 
upstream W3C context into the exception handler / 500 response / error-path 
spans.
   
   Fixed by adding an `except BaseException:` arm (ordered after `except 
GeneratorExit:`, since `GeneratorExit` is a `BaseException`) that detaches and 
re-raises. The detach there is wrapped in `contextlib.suppress(Exception)` so a 
detach failure can't mask the original route exception (preserving the 
`test_route_exception_not_masked_by_detach_error` invariant). Only the 
cross-task `GeneratorExit` force-close skips detach now.
   
   ---
   Drafted-by: Claude Code (Opus 4.8) (reviewed by @dheerajturaga before 
posting)



##########
airflow-core/src/airflow/api_fastapi/execution_api/app.py:
##########
@@ -253,9 +252,16 @@ async def _extract_w3c_trace_context(
     token = otel_context.attach(ctx)
     try:
         yield
-    finally:
-        with contextlib.suppress(Exception):
-            otel_context.detach(token)
+    except GeneratorExit:
+        # The dependency generator was force-closed (client disconnect / 
request
+        # cancellation): the finalizer runs in a different asyncio Task — and 
thus a
+        # different contextvars.Context — than attach did, so detaching the 
token would
+        # raise "Token was created in a different Context" (which OTel logs at 
ERROR
+        # before any suppression here could see it). The attached Context is 
being
+        # discarded with the dying task, so detaching is unnecessary; skip it 
and re-raise.
+        raise
+    else:
+        otel_context.detach(token)

Review Comment:
   Great catch — you're right, and it was a regression. FastAPI finalizes this 
dependency by `athrow`-ing the route exception into the generator at the 
`yield` (confirmed via `_solve_generator` -> `asynccontextmanager` -> 
`AsyncExitStack`), which took neither branch, so detach was skipped on a 
same-task path where it both should and would have succeeded — leaking the 
upstream W3C context into the exception handler / 500 response / error-path 
spans.
   
   Fixed by adding an `except BaseException:` arm (ordered after `except 
GeneratorExit:`, since `GeneratorExit` is a `BaseException`) that detaches and 
re-raises. The detach there is wrapped in `contextlib.suppress(Exception)` so a 
detach failure can't mask the original route exception (preserving the 
`test_route_exception_not_masked_by_detach_error` invariant). Only the 
cross-task `GeneratorExit` force-close skips detach now.
   
   ---
   Drafted-by: Claude Code (Opus 4.8) (reviewed by @dheerajturaga)



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to