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

   `Credentials.load()` guarded only against the credentials file being absent. 
Anything
   else that stopped it being read reached the operator as a Python stack 
trace, because
   none of those exception types are ones `safe_call_command` recognises:
   
   | file state | before |
   | --- | --- |
   | wrong permissions | `PermissionError` traceback |
   | non-UTF-8 bytes | `UnicodeDecodeError` traceback |
   | truncated or empty | `JSONDecodeError` traceback |
   | valid JSON, wrong shape | `TypeError` traceback |
   | no `api_url` key | `KeyError: 'api_url'` traceback |
   
   `$AIRFLOW_HOME/production.json` is a generic name in a shared directory, so 
a foreign
   or half-written file is not far-fetched.
   
   `_read_cli_config` takes the path and owns the open, which is what puts all 
of those
   in one place — `OSError` covers the unreadable paths and `ValueError` covers 
both
   `JSONDecodeError` and `UnicodeDecodeError`, which are siblings rather than 
parent and
   child. `FileNotFoundError` is re-raised untouched so the callers keep 
handling an
   absent file as the distinct case it is. The debug-credentials read in the 
same
   function goes through the helper too.
   
   The tolerance that lets `auth login` run without a credentials file now 
covers an
   unusable one as well. Without that, the error tells the operator to log in 
again and
   the same error blocks them from doing it; the only way out was deleting the 
file by
   hand.
   
   `safe_call_command` catches `AirflowCtlException` rather than a 
hand-maintained tuple
   of five subclasses. The tuple was already equivalent to the base class, and 
keeping it
   manual means the next exception class added anywhere regresses to a 
traceback — the
   same failure this PR is fixing. One side effect worth noting: the 
path-traversal guard
   in `_safe_path_under_airflow_home` raises `AirflowCtlException` directly and 
so was not
   being caught before; it now renders as a message instead of a traceback.
   
   Deliberately out of scope: `{"api_url": null}` still loads as `None` and lets
   `get_client` fall back to `localhost:8080`. That is a silently-wrong-server 
bug rather
   than a traceback, `Credentials.save()` itself writes such a file, and an 
existing test
   covers the current behaviour — it wants its own change. `auth list-envs` 
also reads the
   same file through its own logic, which now defines "unusable" slightly 
differently.
   
   ---
   
   ##### Was generative AI tooling used to co-author this PR?
   
   - [X] Yes — Claude Code (Opus 5)
   
   Generated-by: Claude Code (Opus 5) following [the 
guidelines](https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions)


-- 
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