Callbacks and Error Handling
Purpose and Scope
This page explains how Airflow users should think about operational recovery hooks and error visibility together. A callback is user-supplied Python behavior that Airflow runs around task or DAG lifecycle events, usually to notify an external system, open an incident, or perform cleanup. Error handling is the broader runtime and administration discipline of finding failures, separating user-code errors from platform errors, and giving operators enough context to recover. The official documentation places callbacks and error tracking under Logging & Monitoring, which is the right mental model: callbacks emit responses to lifecycle events, while error surfaces help humans understand what happened.
Airflow has multiple error classes that appear at different points in the workflow lifecycle. A task failure happens after a DAG has been parsed and scheduled. A DAG import error happens earlier, when Airflow parses DAG files and cannot import or evaluate them successfully. Bulk action errors happen in the UI or REST-driven workflows when a user asks Airflow to change several entities and some per-entity operations fail. Treating these as separate signals matters because the recovery path differs: fix DAG code for import errors, inspect task logs and callbacks for task failures, and review per-action feedback for UI or API operations.
Sources: airflow-core/src/airflow/models/errors.py, airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/DagImportErrors.tsx, airflow-core/src/airflow/ui/src/components/ActionErrors.tsx
Relevant Source Files
airflow-core/src/airflow/models/errors.py- DefinesParseImportError, the ORM model for import errors recorded while parsing DAGs and displayed by the webserver.airflow-core/src/airflow/migrations/versions/0069_3_0_3_delete_import_errors.py- Defines an Alembic migration for Airflow 3.0.3 that deletes rows from theimport_errortable during upgrade.airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/DagImportErrors.tsx- Implements the dashboard status card or icon badge that shows DAG import error counts and opens the import-error modal.airflow-core/src/airflow/ui/src/components/ActionErrors.tsx- Renders request-level errors and per-entity bulk-action errors in the React UI.docs/images/documentation_architecture.py- Shows that Airflow documentation is generated and published from repository sources into the live documentation site, which is relevant because callback and error-tracking guidance is part of the published operational docs.
Callback Model for Failure Handling
Airflow callbacks are best used as operational hooks rather than as primary business logic. The official callbacks guide describes callback types and context mapping, including callbacks attached to tasks and DAGs, examples using custom callback methods, notifiers, and deadline alert callbacks. In practice, a callback receives Airflow context and can translate a lifecycle event into a notification, ticket, metrics event, or recovery workflow. Because callbacks execute as part of Airflow operations, they should be fast, deterministic, and defensive: notification failure should not obscure the original task failure.
For failure handling, separate the event from the response. The event is usually a task state transition such as failure, retry, success, execute, or skipped, or a DAG-level outcome. The response is what your callback does with that context. A team may send a Slack alert for a task failure, create a PagerDuty incident for a missed deadline, or write additional audit metadata for a DAG-level failure. The important design constraint is that the callback should enrich observability and recovery without becoming another hidden dependency that makes the orchestration layer fragile.
The official error-tracking page also describes Sentry-oriented setup, tags, breadcrumbs, and the impact of Sentry on environment variables passed to subprocess hooks. That terminology is useful when designing callbacks because a callback and an error tracker often consume the same incident context. Use callbacks when you need Airflow-controlled lifecycle reactions, and use error tracking when you need centralized exception aggregation and correlation across components. In a production deployment, both mechanisms should be aligned with task logs, audit expectations, and the operational ownership model for each DAG.
Import Errors as a First-Class Operational Signal
The source-backed import-error model is ParseImportError. It maps to the import_error table and stores an optional timestamp, filename, bundle name, and stacktrace. Its docstring states the purpose directly: it stores import errors recorded while parsing DAGs and displayed on the webserver. The model also includes full_file_path(), which requires both bundle_name and filename, resolves the bundle through DagBundlesManager, and joins the bundle path with the file name. That makes the error actionable by tying the parsed DAG error back to a concrete file location.
Sources: airflow-core/src/airflow/models/errors.py
Import errors are different from task failures because they prevent a DAG file from becoming a normal schedulable object. If Python code cannot be imported, provider dependencies are absent, or module-level DAG construction raises an exception, task-level callbacks may never run because the tasks were never successfully loaded. Operators should therefore monitor import-error surfaces independently from task-failure alerting. The model’s stacktrace field is especially important: it preserves parser-time exception details for webserver display, so the first recovery action is usually to inspect the import error, reproduce the import locally, and redeploy corrected DAG code.
The Airflow 3.0.3 migration named 0069_3_0_3_delete_import_errors.py performs a targeted cleanup by executing DELETE FROM import_error in upgrade() and leaving downgrade() as a no-op. Operationally, this tells administrators that import-error rows are treated as transient parser state rather than durable audit history. After an upgrade that applies this migration, stale import-error rows are removed and current parser activity will repopulate the table if errors still exist. Do not rely on the import_error table as a long-term incident archive; export incident data to logs, metrics, or an error tracker if retention is required.
Sources: airflow-core/src/airflow/migrations/versions/0069_3_0_3_delete_import_errors.py
UI Surfaces for Errors
The dashboard implementation makes import errors visible without requiring the user to inspect the database. DagImportErrors calls the generated OpenAPI query hook useImportErrorServiceGetImportErrors with limit: 1, then reads total_entries to determine whether any import errors exist. While the request is loading it shows a skeleton. If the count is zero it renders nothing. If errors exist, it renders either a compact failed-state badge or a StatsCard, and clicking the control opens DagImportErrorsModal. This flow keeps the dashboard quiet in the healthy case and prominent when parser errors need attention.
Sources: airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/DagImportErrors.tsx
ActionErrors handles another class of error: failures returned from a bulk action. Its props include an optional BulkActionResponse and an unknown request-level error. The component always renders ErrorAlert for the request-level failure path, then maps actionResponse.errors into individual error alerts. Each bulk action error has an error string and may include a status_code, although this component displays the error message as the alert title. This distinction is useful in administration screens where one API call may partially succeed and still produce per-entity failures that require user attention.
Sources: airflow-core/src/airflow/ui/src/components/ActionErrors.tsx
Compact Reference
| Surface | Concrete name | What it represents | Recovery use |
|---|---|---|---|
| ORM model | ParseImportError | Parser/import failures stored in import_error | Inspect filename, bundle, timestamp, and stacktrace before expecting a DAG to schedule |
| Database table | import_error | Webserver-visible import-error storage | Treat as current operational state, not permanent incident history |
| Model method | full_file_path() | Resolves a DAG bundle path plus filename | Use the resolved path to locate the broken DAG file |
| Migration | upgrade() in 0069_3_0_3_delete_import_errors.py | Deletes rows from import_error for the Airflow 3.0.3 migration | Expect stale import errors to be cleared during upgrade |
| UI component | DagImportErrors | Dashboard card or icon for import-error count | Click through to the modal when count is non-zero |
| UI component | ActionErrors | Request-level and bulk-action error renderer | Read both the main request error and each per-entity action error |
A practical callback and error-handling setup should connect these surfaces rather than duplicate them. Use task and DAG callbacks for lifecycle notifications that only make sense after a DAG has loaded. Use the import-error dashboard card to catch parser failures that occur before callbacks can run. Use bulk-action error alerts when operating the UI or REST-backed screens, because a request can have a mixed outcome. Finally, if your organization uses centralized error tracking, align Sentry tags and breadcrumbs with Airflow identifiers such as DAG ID, task ID, run ID, and deployment environment so incidents can be traced back to Airflow state.
Documentation and Release Context
The documentation architecture script is not part of runtime error handling, but it explains why the official callbacks and error-tracking pages should be treated as part of the product surface. The diagram generator models Airflow GitHub repositories, release-manager publishing, S3-hosted package docs, CloudFront caching, and the live airflow.apache.org site. That source-backed publication path matters for operators: callback behavior, notifier examples, and error-tracking guidance are not ad hoc wiki notes; they are versioned documentation shipped with the Airflow release stream.
Sources: docs/images/documentation_architecture.py
When implementing a recovery strategy, start with the official callback examples and decide which lifecycle events need notifications. Then verify that DAG import errors are visible in your UI and included in operational runbooks, because those failures bypass task callbacks. Next, test one successful callback, one failing task, one broken DAG import, and one partial bulk action in a non-production environment. The next related topics to read are task logs for root-cause detail, metrics and health checks for monitoring, and secrets masking if callbacks or error trackers may receive sensitive context.