When a newly deployed DAG file fails to appear in the Airflow web UI, the issue is almost always a parsing failure, a directory path mismatch, or a failed discovery heuristic.
Step 1: Check UI import errors
Look at the top of the Airflow UI home page. If a DAG file contains a Python syntax error, a missing third-party library, or a failed import, Airflow displays a red banner titled "DAG Import Errors". Click the banner to view the full stack trace. Alternatively, run the CLI command:
airflow dags list-import-errors
This immediately pinpoints the exact line of code that failed during parsing.
Step 2: The safe mode keyword heuristic
A classic trap that catches engineers is Airflow's DAG discovery safe mode. Controlled by the setting DAG_DISCOVERY_SAFE_MODE (enabled by default), Airflow ignores any Python file in the DAGs folder unless the file contains the literal strings airflow or DAG (case-insensitive) anywhere in the text.
If you generate DAGs using an abstracted helper function imported from an internal library:
# This file will be ignored by default if neither "airflow" nor "DAG" appears in the text from my_company_library import build_standard_pipeline pipeline = build_standard_pipeline(table="orders")
The file parser skips this file without throwing an error. Adding a comment like # airflow pipeline definition resolves the issue.
Step 3: File location and deployment synchronization
Confirm the file actually exists inside the directory configured as core.dags_folder. If using Kubernetes with a Git-sync sidecar, check the sidecar logs to verify that the latest Git commit was pulled successfully and was not blocked by authentication or branch merge conflicts.
Step 4: Duplicate dag_id
If two different Python files define a DAG with the identical dag_id, Airflow parses one and ignores the other, or overwrites it in the database. Ensure the dag_id is globally unique.
Step 5: Processor health and timeouts
Verify that the DAG processor component is running and healthy. If the new file executes slow top-level code (like querying a database), the parser may exceed dagbag_import_timeout (30 seconds) and terminate processing before registering the DAG. Note that newly added DAGs are paused by default, but they still appear in the list unless filtered out.