Skip to content

Fix Dag serialization crash for Task SDK EventsTimetable - #69401

Open
anxkhn wants to merge 2 commits into
apache:mainfrom
anxkhn:patch-3
Open

Fix Dag serialization crash for Task SDK EventsTimetable#69401
anxkhn wants to merge 2 commits into
apache:mainfrom
anxkhn:patch-3

Conversation

@anxkhn

@anxkhn anxkhn commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Any Dag scheduled with the Task SDK EventsTimetable
(from airflow.sdk import EventsTimetable) currently fails to serialize with
SerializationError: Failed to serialize DAG '...': '_summary', so the Dag
cannot be parsed or scheduled.

The SDK timetable serializer in airflow-core/src/airflow/serialization/encoders.py
emits only {event_dates, restrict_to_events, description} and omits the
_summary key, but the core EventsTimetable.deserialize in
airflow-core/src/airflow/timetables/events.py read data["_summary"]
unconditionally and raised KeyError when it was absent. The two are
asymmetric: _summary became a required serialized field in #51203, and the
SDK serializer that omits it was added in #58669.

This makes deserialize retain the summary already computed by
EventsTimetable.__init__ when _summary is absent. Dags using the SDK
timetable serialize and schedule again, while existing serialized data that
still carries _summary keeps its stored value.

A parametrized regression test round-trips a Dag scheduled with the SDK
EventsTimetable through DagSerialization with and without a description
and asserts the summary is preserved.


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

Comment thread airflow-core/src/airflow/timetables/events.py Outdated
@Vamsi-klu

Copy link
Copy Markdown
Contributor

Confirmed the root cause: the SDK serialize_timetable for EventsTimetable in serialization/encoders.py emits only event_dates/restrict_to_events/description and omits _summary (which #51203 made a field the core deserialize read unconditionally), so a DAG using from airflow.sdk import EventsTimetable serializes fine but KeyErrors on deserialize -> SerializationError. data.get("_summary", timetable._summary) is safe because core init always sets self._summary (the description if given, else "{n} events"), and existing core-serialized payloads that still carry _summary keep their stored value. The parametrized test reproduces both branches and KeyErrors without the change. One thing worth stating explicitly: the deserialize-side fix is the correct location regardless of any encoder change, because serialized_dag rows already written since #58669 lack _summary, so tolerating its absence on read is required to recover them, whereas emitting _summary only from the SDK encoder would leave already-persisted DAGs broken. FWIW the .get() form is functionally identical to the contextlib.suppress(KeyError) suggestion in the thread. Minor: the newsfragment is named 69283.bugfix.rst but #69283 is an unrelated merged PR, presumably a placeholder to rename to the real number.

A Dag scheduled with the Task SDK EventsTimetable failed to serialize
because the SDK timetable serializer omits the _summary key, while the
core EventsTimetable.deserialize required it unconditionally and raised
KeyError. Fall back to the summary computed by __init__ when the key is
absent, so Dags using the SDK timetable serialize and schedule again
while existing serialized data keeps its stored summary.

Signed-off-by: Anas Khan <83116240+anxkhn@users.noreply.github.com>
@potiuk potiuk added the ready for maintainer review Set after triaging when all criteria pass. label Jul 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:DAG-processing ready for maintainer review Set after triaging when all criteria pass.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants