Skip to content

Fix XCom migration failing for NaN/Infinity float values#62686

Merged
vatsrahul1001 merged 2 commits intoapache:mainfrom
astronomer:fix_xcom_migration_nan_inf
Mar 3, 2026
Merged

Fix XCom migration failing for NaN/Infinity float values#62686
vatsrahul1001 merged 2 commits intoapache:mainfrom
astronomer:fix_xcom_migration_nan_inf

Conversation

@jedcunningham
Copy link
Copy Markdown
Member

XCom values containing float('nan'), float('inf'), or float('-inf') caused the database migration to silently corrupt data or fail outright when upgrading. Three bugs were present across backends:

  • Consecutive tokens (e.g. [NaN, NaN]) were only partially replaced, leaving bare NaN/Infinity in the output and breaking the JSON cast.
  • Infinity and -Infinity were not handled at all — only NaN was.
  • Bare top-level values (a single NaN or Infinity, not inside a list or dict) were not matched and passed through unconverted.

MySQL also had two bugs in the replacement query that caused it to produce the wrong output (one of these was pre-existing from #57866).

An example of a failing Infinity in xcom:

2026-03-02T03:23:06.876232Z [info     ] Running upgrade 9fc3fc5de720 -> eed27faa34e3, Remove pickled data from xcom table. [alembic.runtime.migration] loc=m
igration.py:621
Traceback (most recent call last):
  File "/usr/python/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context
    self.dialect.do_execute(
  File "/usr/python/lib/python3.12/site-packages/sqlalchemy/engine/default.py", line 952, in do_execute
    cursor.execute(statement, parameters)
psycopg2.errors.InvalidTextRepresentation: invalid input syntax for type json
DETAIL:  Token "Infinity" is invalid.
CONTEXT:  JSON data, line 1: Infinity
…
sqlalchemy.exc.DataError: (psycopg2.errors.InvalidTextRepresentation) invalid input syntax for type json
DETAIL:  Token "Infinity" is invalid.
CONTEXT:  JSON data, line 1: Infinity

[SQL:
            ALTER TABLE xcom
            ALTER COLUMN value TYPE JSONB
            USING CASE
                WHEN value IS NOT NULL THEN CAST(CONVERT_FROM(value, 'UTF8') AS JSONB)
                ELSE NULL
            END
            ]
(Background on this error at: https://sqlalche.me/e/20/9h9h)

A Dag that can be used to test:

from __future__ import annotations

try:
    from airflow.sdk import DAG, task
except ImportError:
    from airflow import DAG
    from airflow.decorators import task


@task
def push_nan_values():
    return {
        "nan_value": float("nan"),
        "nested": {
            "stats": {
                "count": 1.0,
                "mean": 0.196,
                "std": float("nan"),
            },
            "list_of_nans": [float("nan"), float("nan"), float("nan")],
        },
        "normal_value": 42,
    }


@task
def push_inf_values():
    return {
        "inf_value": float("inf"),
        "neg_inf_value": float("-inf"),
        "nested": {
            "stats": {
                "count": 1.0,
                "mean": 0.196,
                "min": float("-inf"),
                "max": float("inf"),
            },
            "list_of_infs": [float("inf"), float("-inf"), float("inf"), float("-inf")],
        },
        "normal_value": 42,
    }


@task
def push_top_level_nan():
    return float("nan")


@task
def push_top_level_inf():
    return float("inf")



with DAG(dag_id="nan_xcom", schedule=None):
    push_nan_values()


with DAG(dag_id="infinity_xcom", schedule=None):
    push_inf_values()


with DAG(dag_id="top_level_nan_xcom", schedule=None):
    push_top_level_nan()


with DAG(dag_id="top_level_inf_xcom", schedule=None):
    push_top_level_inf()


Was generative AI tooling used to co-author this PR?
  • Yes

Generated-by: Cursor

XCom values containing float('nan'), float('inf'), or float('-inf')
caused the database migration to silently corrupt data or fail
outright when upgrading. Three bugs were present across backends:

- Consecutive tokens (e.g. [NaN, NaN]) were only partially replaced,
  leaving bare NaN/Infinity in the output and breaking the JSON cast.
- Infinity and -Infinity were not handled at all — only NaN was.
- Bare top-level values (a single NaN or Infinity, not inside a list
  or dict) were not matched and passed through unconverted.

MySQL also had two bugs in the replacement query that caused it to produce
the wrong output (one of these was pre-existing from apache#57866).
@vatsrahul1001 vatsrahul1001 merged commit 7a301e6 into apache:main Mar 3, 2026
129 checks passed
@vatsrahul1001 vatsrahul1001 deleted the fix_xcom_migration_nan_inf branch March 3, 2026 03:46
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 3, 2026

Backport failed to create: v3-1-test. View the failure log Run details

Note: As of Merging PRs targeted for Airflow 3.X
the committer who merges the PR is responsible for backporting the PRs that are bug fixes (generally speaking) to the maintenance branches.

In matter of doubt please ask in #release-management Slack channel.

Status Branch Result
v3-1-test Commit Link

You can attempt to backport this manually by running:

cherry_picker 7a301e6 v3-1-test

This should apply the commit to the v3-1-test branch and leave the commit in conflict state marking
the files that need manual conflict resolution.

After you have resolved the conflicts, you can continue the backport process by running:

cherry_picker --continue

If you don't have cherry-picker installed, see the installation guide.

jedcunningham added a commit to astronomer/airflow that referenced this pull request Mar 3, 2026
XCom values containing float('nan'), float('inf'), or float('-inf')
caused the database migration to silently corrupt data or fail
outright when upgrading. Three bugs were present across backends:

- Consecutive tokens (e.g. [NaN, NaN]) were only partially replaced,
  leaving bare NaN/Infinity in the output and breaking the JSON cast.
- Infinity and -Infinity were not handled at all — only NaN was.
- Bare top-level values (a single NaN or Infinity, not inside a list
  or dict) were not matched and passed through unconverted.

MySQL also had two bugs in the replacement query that caused it to produce
the wrong output (one of these was pre-existing from apache#57866).

Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
(cherry picked from commit 7a301e6)
jedcunningham added a commit that referenced this pull request Mar 3, 2026
…2760)

XCom values containing float('nan'), float('inf'), or float('-inf')
caused the database migration to silently corrupt data or fail
outright when upgrading. Three bugs were present across backends:

- Consecutive tokens (e.g. [NaN, NaN]) were only partially replaced,
  leaving bare NaN/Infinity in the output and breaking the JSON cast.
- Infinity and -Infinity were not handled at all — only NaN was.
- Bare top-level values (a single NaN or Infinity, not inside a list
  or dict) were not matched and passed through unconverted.

MySQL also had two bugs in the replacement query that caused it to produce
the wrong output (one of these was pre-existing from #57866).


(cherry picked from commit 7a301e6)

Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
vatsrahul1001 added a commit that referenced this pull request Mar 4, 2026
…2760)

XCom values containing float('nan'), float('inf'), or float('-inf')
caused the database migration to silently corrupt data or fail
outright when upgrading. Three bugs were present across backends:

- Consecutive tokens (e.g. [NaN, NaN]) were only partially replaced,
  leaving bare NaN/Infinity in the output and breaking the JSON cast.
- Infinity and -Infinity were not handled at all — only NaN was.
- Bare top-level values (a single NaN or Infinity, not inside a list
  or dict) were not matched and passed through unconverted.

MySQL also had two bugs in the replacement query that caused it to produce
the wrong output (one of these was pre-existing from #57866).


(cherry picked from commit 7a301e6)

Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
dominikhei pushed a commit to dominikhei/airflow that referenced this pull request Mar 11, 2026
XCom values containing float('nan'), float('inf'), or float('-inf')
caused the database migration to silently corrupt data or fail
outright when upgrading. Three bugs were present across backends:

- Consecutive tokens (e.g. [NaN, NaN]) were only partially replaced,
  leaving bare NaN/Infinity in the output and breaking the JSON cast.
- Infinity and -Infinity were not handled at all — only NaN was.
- Bare top-level values (a single NaN or Infinity, not inside a list
  or dict) were not matched and passed through unconverted.

MySQL also had two bugs in the replacement query that caused it to produce
the wrong output (one of these was pre-existing from apache#57866).

Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants