Context
While reviewing #67877 (which adds a task.execute detail span), we found that the worker-level OTel span (worker.<task_id>, created unconditionally in _make_task_span in task-sdk/src/airflow/sdk/execution_time/task_runner.py) is not consistently marked with an ERROR status when a task fails.
run() catches every exception from task execution — down to except BaseException — and converts it to a terminal state plus a supervisor message without re-raising. Because the exception never propagates out through the worker span's with block, OpenTelemetry's automatic set_status_on_exception never fires, and the worker span is left with status UNSET on failure.
An earlier iteration of #67877 set the span status explicitly in the execution-timeout handler. But at task-span detail level 1 (where the task.execute / _execute_task / run detail spans don't exist) trace.get_current_span() resolved to the worker span, so a timeout marked the worker span ERROR while an ordinary failure did not — an inconsistency. That explicit status handling was removed from #67877 to keep it scoped to "add the span"; the holistic fix is tracked here.
Proposed work
Mark the worker.<task_id> span with an ERROR status for all terminal task failures (regular Exception, AirflowTaskTimeout, AirflowFailException, AirflowSensorTimeout, AirflowTaskTerminated, SystemExit, and the catch-all BaseException path), consistently and independent of trace detail level. Successful / skipped / up_for_reschedule / deferred outcomes should keep their current (non-error) status.
This likely belongs in run(), where the terminal state is already determined, rather than scattered across _run_execute_callable / _execute_task — so the span status is derived once from the final task state rather than from get_current_span().
Acceptance criteria
- A task that fails (any of the failure exception types above) produces a
worker.<task_id> span with status ERROR.
- The behaviour is identical regardless of
task_span_detail_level.
- Non-failure terminal states (success, skipped, up_for_reschedule, deferred) do not get an
ERROR status.
- Tests cover at least: regular exception, execution timeout, and a successful run.
Found during review of #67877.
Drafted-by: Claude Code (Opus 4.8) (no human review before posting)
Context
While reviewing #67877 (which adds a
task.executedetail span), we found that the worker-level OTel span (worker.<task_id>, created unconditionally in_make_task_spanintask-sdk/src/airflow/sdk/execution_time/task_runner.py) is not consistently marked with an ERROR status when a task fails.run()catches every exception from task execution — down toexcept BaseException— and converts it to a terminal state plus a supervisor message without re-raising. Because the exception never propagates out through the worker span'swithblock, OpenTelemetry's automaticset_status_on_exceptionnever fires, and the worker span is left with statusUNSETon failure.An earlier iteration of #67877 set the span status explicitly in the execution-timeout handler. But at task-span detail level 1 (where the
task.execute/_execute_task/rundetail spans don't exist)trace.get_current_span()resolved to the worker span, so a timeout marked the worker spanERRORwhile an ordinary failure did not — an inconsistency. That explicit status handling was removed from #67877 to keep it scoped to "add the span"; the holistic fix is tracked here.Proposed work
Mark the
worker.<task_id>span with anERRORstatus for all terminal task failures (regularException,AirflowTaskTimeout,AirflowFailException,AirflowSensorTimeout,AirflowTaskTerminated,SystemExit, and the catch-allBaseExceptionpath), consistently and independent of trace detail level. Successful / skipped / up_for_reschedule / deferred outcomes should keep their current (non-error) status.This likely belongs in
run(), where the terminal state is already determined, rather than scattered across_run_execute_callable/_execute_task— so the span status is derived once from the final task state rather than fromget_current_span().Acceptance criteria
worker.<task_id>span with statusERROR.task_span_detail_level.ERRORstatus.Found during review of #67877.
Drafted-by: Claude Code (Opus 4.8) (no human review before posting)