Eason09053360 opened a new pull request, #72893:
URL: https://github.com/apache/airflow/pull/72893

   `airflow backfill create --dag-id <unknown>` now prints a one-line error and 
exits 1 instead of dumping a `DagNotFound` traceback, in both the normal and 
`--dry-run` paths.
   
   ### Why
   
   Mistyping the Dag id is the most ordinary user error this command can see, 
and today it looks like a crash:
   
       $ airflow backfill create --dag-id does_not_exist --from-date 2025-01-01 
--to-date 2025-01-02
       Traceback (most recent call last):
         ...
         File ".../airflow/models/backfill.py", line 641, in _create_backfill
           raise DagNotFound(f"Could not find dag {dag_id}")
       airflow.exceptions.DagNotFound: Could not find dag does_not_exist
   
   The model layer raises `DagNotFound` on purpose (it serves both the REST API 
and the CLI), and the REST route already maps it to a 404. The CLI handler only 
caught `NoBackfillRunsToCreate`, so this exception escaped untranslated. Every 
other CLI "Dag does not exist" path (`dags list-jobs`, `dags list-runs`, `dags 
state`, ...) already reports it as a plain message on stderr.
   
   The `--dry-run` path had a second wrinkle: `_do_dry_run` is a generator, so 
its body (including the Dag lookup that raises) only ran when the result was 
iterated, which happened after the `create_session()` block had exited and 
outside any `try`.
   
   ### What
   
   - Catch `DagNotFound` at the CLI boundary and re-raise it as 
`SystemExit(str(e))`, which writes the message to stderr and exits 1, the same 
idiom the other CLI "not found" paths use. The exit code is unchanged from the 
traceback case, so scripts checking `$?` see no difference.
   - In the dry-run branch, consume `_do_dry_run(...)` with `list(...)` inside 
the session block and the `try`. Without this the new handler would be 
unreachable, because the exception surfaces on iteration, not on the call. As a 
side effect the generator now runs while the session it was given is still 
open; previously it ran after `session.close()`.
   
   Deliberately out of scope: the sibling validation errors from the same two 
model calls (`AlreadyRunningBackfill`, `DagNonPeriodicScheduleException`, 
`DagRunTypeNotAllowed`, `InvalidBackfillDateRange`, ...) still surface as 
tracebacks. They share the root cause but each needs its own message and test; 
this PR only fixes the missing-Dag case. Happy to follow up with the rest if 
reviewers prefer one PR.
   
   ### How to test
   
   Automated, `airflow-core/tests/unit/cli/commands/test_backfill_command.py`:
   
   - `TestCliBackfill::test_backfill_unknown_dag_shows_friendly_message[False]` 
and `[True]` (the `True` case is `--dry-run`). They hit the real database (the 
module's `setup_method` empties the `dag` table, so the Dag is guaranteed 
missing) and assert `SystemExit` with the Dag id in the message. On `main` both 
fail because `DagNotFound` propagates instead.
   - `uv run --project airflow-core pytest 
airflow-core/tests/unit/cli/commands/test_backfill_command.py -k unknown_dag 
-xvs`
   - The rest of the file was run as well; the pre-existing `test_backfill*` 
cases that mock `_create_backfill` are unaffected (they fail on a non-root host 
for an unrelated `triggering_user_name='root'` assumption, and pass in Breeze).
   
   Manual, against a fresh `airflow db migrate` SQLite database (stdout and 
stderr captured separately):
   
   - `airflow backfill create --dag-id does_not_exist --from-date 2025-01-01 
--to-date 2025-01-02` prints `Could not find dag does_not_exist` on stderr, 
nothing on stdout, exit 1 (before: traceback, exit 1).
   - Same command with `--dry-run` prints the params block on stdout, then 
`Could not find Dag does_not_exist` on stderr, exit 1.
   - `--dag-id '[/b]x'` prints `Could not find dag [/b]x` verbatim; square 
brackets are not interpreted as rich markup.
   
   ---
   
   ##### Was generative AI tooling used to co-author this PR?
   
   - [X] Yes — Claude Code (Fable 5.1)
   
   Generated-by: Claude Code (Fable 5.1) following [the 
guidelines](https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions)
   
   ---
   
   * Read the **[Pull Request 
Guidelines](https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#pull-request-guidelines)**
 for more information. Note: commit author/co-author name and email in commits 
become permanently public when merged.
   * For fundamental code changes, an Airflow Improvement Proposal 
([AIP](https://cwiki.apache.org/confluence/display/AIRFLOW/Airflow+Improvement+Proposals))
 is needed.
   * When adding dependency, check compliance with the [ASF 3rd Party License 
Policy](https://www.apache.org/legal/resolved.html#category-x).
   * For significant user-facing changes create newsfragment: 
`{pr_number}.significant.rst`, in 
[airflow-core/newsfragments](https://github.com/apache/airflow/tree/main/airflow-core/newsfragments).
 You can add this file in a follow-up commit after the PR is created so you 
know the PR number.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to