Migration Checklist
After running Ruff's AIR rules, use this manual search checklist to find remaining issues.
1. Direct metadata DB access
Search for:
provide_sessioncreate_session@provide_sessionSession(enginewith Session()engine.connect(Session(bind=engine)from airflow.settings import Sessionfrom airflow.settings import enginefrom sqlalchemy.orm.session import Session
Fix: Refactor to use Airflow Python client or REST API
2. Legacy imports
Search for:
from airflow.contribfrom airflow.operators.from airflow.hooks.
Fix: Map to provider imports (see migration-patterns.md)
3. Removed/renamed DAG arguments
Search for:
schedule_interval=timetable=days_ago(fail_stop=sla=sla_miss_callback
Fix:
schedule_intervalandtimetable→ useschedule=days_ago→ usependulum.today("UTC").add(days=-N)fail_stop→ renamed tofail_fastslaandsla_miss_callback→ removed; use Astro Alerts or OSS Deadline Alerts (Airflow 3.1+ experimental)
4. Deprecated context keys
Search for:
execution_dateprev_dsnext_dsyesterday_dstomorrow_dstemplates_dict
Fix:
execution_date→ usecontext["dag_run"].logical_datetomorrow_ds/yesterday_ds→ usedswith date math:macros.ds_add(ds, 1)/macros.ds_add(ds, -1)prev_ds/next_ds→ useprev_start_date_successor timetable APItemplates_dict→ useparamsviacontext["params"]
5. XCom pickling
Search for:
ENABLE_XCOM_PICKLING.xcom_pull(withouttask_ids=
Fix: Use JSON-serializable data or custom backend
6. Datasets to Assets
Search for:
airflow.datasetstriggering_dataset_eventsDatasetOrTimeScheduleon_dataset_createdon_dataset_changedoutlet_events["inlet_events["
Fix: Switch to airflow.sdk.Asset, AssetOrTimeSchedule, on_asset_created/on_asset_changed. Use Asset(name=...) objects as keys in outlet_events/inlet_events (not strings)
7. Removed operators
Search for:
SubDagOperatorSimpleHttpOperatorDagParamDummyOperator
Fix: Use TaskGroups, HttpOperator, Param, EmptyOperator
8. Email changes
Search for:
airflow.operators.email.EmailOperatorairflow.utils.emailemail=(task parameter for email on failure/retry)
Fix: Use SMTP provider (apache-airflow-providers-smtp). Replace legacy email behavior with SMTP-provider callbacks such as send_smtp_notification(...) or SmtpNotifier.
9. REST API v1
Search for:
/api/v1auth=(execution_date(in API params)
Fix: Update to /api/v2 with Bearer tokens. Replace execution_date params with logical_date. Dataset endpoints now under asset resources
10. File paths
Search for:
open("include/open("data/template_searchpath=- relative paths
Fix: Use __file__ or AIRFLOW_HOME anchoring. Note: triggers cannot be in DAG bundle; must be elsewhere on sys.path
11. FAB-based plugins
Search for:
appbuilder_viewsappbuilder_menu_itemsflask_blueprintsAirflowPlugin
Fix: Flask-AppBuilder removed from core. FAB plugins need manual migration to new system (React apps, FastAPI, listeners). Do not auto-migrate; recommend separate PR
12. Callback and behavior changes
Search for:
on_success_callback@teardowntemplates_dictexpanded_ti_countexternal_triggertest_modetrigger_rule="dummy"orTriggerRule.DUMMYtrigger_rule="none_failed_or_skipped"orNONE_FAILED_OR_SKIPPED
Fix:
on_success_callbackno longer runs on skip; useon_skipped_callbackif needed@teardownwith trigger rulealwaysnot allowed; teardowns now execute even if DAG run terminated earlytemplates_dictremoved → useparamsviacontext["params"]expanded_ti_countremoved → use REST API "Get Mapped Task Instances"dag_run.external_triggerremoved → infer fromdag_run.run_typetest_moderemoved; avoid relying on this flagdummytrigger rule removed → usealways(orTriggerRule.ALWAYS)none_failed_or_skippedtrigger rule removed → usenone_failed_min_one_success(orTriggerRule.NONE_FAILED_MIN_ONE_SUCCESS)