Skip to content

UI DAG run stats endpoint returns 500 on PostgreSQL: TypeError: unsupported operand type(s) for *: 'decimal.Decimal' and 'float #71497

Description

@illiakrauchanka

Under which category would you file this issue?

Airflow Core

Apache Airflow version

3.3.0

What happened and how to reproduce it?

If "Other Airflow 2/3 version" selected, which one?

No response

What happened?

On a PostgreSQL metadata database, the UI DAG run stats endpoint returns HTTP 500 for every request:

GET /ui/dags/{dag_id}/dagRuns/{dag_run_id}/stats

[error] Exception in ASGI application [uvicorn.error] loc=httptools_impl.py:426
Traceback (most recent call last):
  ...
  File ".../airflow/api_fastapi/core_api/routes/ui/dag_runs.py", line 63, in get_dag_run_stats
  File ".../airflow/api_fastapi/core_api/services/ui/dag_run.py", line 55, in compute_duration_stats
  File ".../airflow/api_fastapi/core_api/services/ui/dag_run.py", line 50, in _percentile
TypeError: unsupported operand type(s) for *: 'decimal.Decimal' and 'float'

Root cause is a type mismatch between the query and the helper that consumes it.

get_dag_run_stats (core_api/routes/ui/dag_runs.py) selects the SQL expression form of the duration:

durations = [
    d
    for d in session.scalars(
        select(DagRun.duration.expression)
        .where(...)
        .limit(100)
    )
    if d is not None
]
return DagRunStatsResponse(duration=compute_duration_stats(durations))

DagRun.duration.expression (models/dagrun.py) is dialect dependent:

  • PostgreSQL: func.extract("epoch", cls.end_date - cls.start_date) -> SQL numeric -> psycopg returns decimal.Decimal
  • MySQL: func.timestampdiff(SECOND, ...) -> integer
  • SQLite: (julianday(end) - julianday(start)) * 86400 -> float

compute_duration_stats is annotated durations: list[float] and mixes the values with plain floats:

def _percentile(p: float) -> float:
    idx = (len(sorted_d) - 1) * p / 100
    lo = int(idx)
    hi = min(lo + 1, len(sorted_d) - 1)
    return sorted_d[lo] + (sorted_d[hi] - sorted_d[lo]) * (idx - lo)

With Decimal values, Decimal * float raises TypeError. This is not limited to the interpolating case: with a single completed run, idx - lo is 0.0 and Decimal(0) * 0.0 raises as well, so any DAG that has at least one completed run fails.

Impact is limited to this endpoint, which the UI calls when a DAG's run stats are displayed. Scheduling, task execution and the public API are unaffected.

What you think should happen instead?

The endpoint should return duration statistics regardless of the metadata database backend.

Coercing at the query boundary keeps compute_duration_stats matching its list[float] annotation:

durations = [float(d) for d in session.scalars(...) if d is not None]

Alternatively _percentile could operate on Decimal consistently, but the boundary cast looks closer to the intent of the existing type hints.

How to reproduce

  1. Deploy Airflow 3.3.0 with a PostgreSQL metadata database.
  2. Let at least one DAG run reach success or failed.
  3. Call GET /ui/dags/{dag_id}/dagRuns/{dag_run_id}/stats, or open the DAG in the UI so the stats panel loads.
  4. The request fails with HTTP 500 and the traceback above.

Not reproducible on SQLite or MySQL, where the same expression yields float / int.

Operating System

Debian GNU/Linux 12 (bookworm) — official apache/airflow:3.3.0 image

Versions of Apache Airflow Providers

No response

Deployment

Official Apache Airflow Helm Chart

Deployment details

Helm chart 1.22.0 with defaultAirflowTag / airflowVersion pinned to 3.3.0, KubernetesExecutor and CeleryExecutor deployments both affected, PostgreSQL 17.9 (Amazon RDS), Python 3.13.

Anything else?

Occurs on every request to the endpoint once a DAG has completed runs.

Are you willing to submit PR?

  • Yes I am willing to submit a PR!

Code of Conduct

What you think should happen instead?

No response

Operating System

No response

Deployment

None

Apache Airflow Provider(s)

No response

Versions of Apache Airflow Providers

No response

Official Helm Chart version

Not Applicable

Kubernetes Version

No response

Helm Chart configuration

No response

Docker Image customizations

No response

Anything else?

No response

Are you willing to submit PR?

  • Yes I am willing to submit a PR!

Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:APIAirflow's REST/HTTP APIarea:MetaDBMeta Database related issues.area:UIRelated to UI/UX. For Frontend Developers.kind:bugThis is a clearly a bugneeds-triagelabel for new issues that we didn't triage yet

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions