Airflow 3.3.1 (12 August 2026)
pandas 3 DataFrame XComs
Airflow now registers both old and new pandas class names so existing XComs stay readable. The release notes warn:
- Roll 3.3.1 out to every component (scheduler, API server, DAG processor, workers, triggerer) before pandas 3 reaches any of them. Older readers fail with an
ImportErroron XComs written under pandas 3. - A downgrade is a one-way door for those XComs. Once a DataFrame XCom is written by the new version with pandas 3, an older Airflow may not read it.
- DAGs that check DataFrame
dtypesmay behave differently under pandas 3.
What to do:
- Pin pandas below 3 in your image until every component runs 3.3.1+.
- Upgrade all components together (one Helm release, one image).
- Then allow pandas 3, and test DAGs that pass DataFrames through XCom (better: pass a path to Parquet in object storage, not the DataFrame).
# which components run which pandas
for d in scheduler api-server dag-processor worker triggerer; do
echo -n "$d: "; kubectl exec deploy/airflow-$d -n airflow -- python -c "import pandas, airflow; print(airflow.__version__, pandas.__version__)"
done
2.x to 3.x upgrade fix for custom DAG bundles
A migration had set legacy DAG rows to the dags-folder bundle, which broke triggering for deployments with custom bundles. 3.3.1 backfills the right bundle at startup, and unmatched DAGs fix themselves on the next successful parse. To force it straight away:
airflow dags reserialize
Also in 3.3.1: legacy DAGs with a NULL bundle_name are deactivated during the 2.x to 3.x upgrade.
Team-scoped sensitive config is masked
GET /config and airflow config list now show < hidden > for team-scoped overrides of sensitive options, including team _cmd and _secret entries. Scripts that read secrets through the config API will now get the placeholder. They should read from the secrets backend instead.
Airflow 3.3.2 (17 September 2026)
Backfill endpoint returns 404 instead of 403
Requesting a backfill on a DAG you can't read now returns 404, and unknown-ID messages changed to Backfill not found. Clients that match on status 403 or on the old detail text need updating.
Explicit credentials beat the session cookie
"An explicit credential now takes precedence over the session cookie."
- A request carrying both a cookie and a bearer token now runs as the token's identity.
- An invalid explicit credential is rejected with 401/403 even if a valid cookie is present.
Where this bites: browser-based tools or internal portals that add a service token to requests while the user is also logged in. Actions now run as the service identity, which may have more or fewer permissions than the user. Review those tools and decide which identity should be used.
Upgrade-related fixes
airflow db migrateno longer fails under PyMySQL when a migration drops unique constraints.- XCom values that already parse as JSON are no longer corrupted during the bytea-to-JSONB migration. If you upgraded across that migration on an earlier version, spot-check old XComs.
Roll-out order
- Read the full release notes for every version you skip.
- Back up the metadata database.
- Pin pandas < 3 until all components are on 3.3.1+.
- Upgrade in staging, run
airflow db migrate, run a representative set of DAGs (including XCom-heavy ones) and your API clients. - Upgrade production, all components together.
There's also an open report of DAG processor timeouts after 3.3.1/3.3.2 on some Kubernetes setups; see the triage post.
Checklist
- pandas pinned below 3 until all components run 3.3.1+
- All Airflow components upgraded together
- DAGs that pass DataFrames through XCom tested
- Scripts no longer read secrets through the config API
- API clients handle 404 / new detail text for backfills
- Tools sending both cookies and tokens reviewed
- Database backup taken before
airflow db migrate