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

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions