Uh oh!
There was an error while loading. Please reload this page.
Decorate custom state refs with an envelope for UI clarity - #67530
Conversation
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
kaxil
left a comment
There was a problem hiding this comment.
Thanks for the thorough follow-ups -- all the points from the last pass are addressed. The move off the __type/__var serialization namespace to __airflow_state_ref__ removes the collision, the _wrap/_unwrap helpers keep the wire format in one place, and the warning-log on the mismatch path is a good safety net. LGTM.
d101f30 to
cc1e888Comparekaxil
commented
May 29, 2026
Rebased your PR on main since it had unrelated spelling failures |
amoghrajesh
commented
May 29, 2026
Thanks for rebasing, @kaxil. I am merging this one in now |
Uh oh!
There was an error while loading. Please reload this page.
Was generative AI tooling used to co-author this PR?
What problem are we solving?
When a custom worker backend (e.g. S3, GCS) stores a state value externally and writes a reference string back to the DB, the UI has no way to tell whether a value like
s3://bucket/ti_123/job_idis:Without this distinction, the UI would show the raw path as if it were the value, which can be confusing and misleading.
Current behaviour
Custom backends return a reference string from
serialize_task_state_to_ref(), which is stored verbatim in the DB. The DB value column contains either a plain JSON value or a reference string with no structural difference between the two — the UI cannot differentiate them.Proposed change
When a custom worker backend is configured, the framework now automatically wraps the reference returned by
serialize_task_state_to_ref()in a typed envelope before storing:{"__airflow_state_ref__": "s3://bucket/ti_123/job_id"}On read, the framework detects the envelope, extracts the ref, and passes it to
deserialize_task_state_from_ref()and the backend never sees the envelope. If a stored value does not carry the marker (e.g. a corrupt row), the raw value is returned and a warning is logged.The default path (no custom backend) is unaffected, plain JSON values are stored and returned as before.
UI Impact
UI PR for reference #67292
The UI reads state values directly from the DB and displays them as-is. With this change, when a custom backend is in use, the UI will show
{"__airflow_state_ref__": "..."}instead of a raw reference string, making it visually clear that the value is a pointer to externally-stored data rather than the actual state value.Testing
Created a custom worker side backend based on file system:
Ran breeze with:
export AIRFLOW__WORKERS__STATE_BACKEND=file_state_backend.FileStateBackendDAG:
The task is agnostic to the envelope.
File system is updated with the custom backend generated files:
Core API will return the external reference for UI to build upon, the extra encoding like
{\"__airflow_state_ref__\": \"/tmp/airflow_state/ti_019e6821-0661-7bdc-ad37-8dad5ac1fa14/int_value.json\"}will be fixed by: #67547{pr_number}.significant.rst, in airflow-core/newsfragments. You can add this file in a follow-up commit after the PR is created so you know the PR number.