Skip to content

Task worker OTel span not marked ERROR on task failures #69144

Description

@dstandish

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)

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions