Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Catch format-string arguments passed to exception constructors - #73076

Draft
rjgoyln wants to merge 1 commit into
apache:mainfrom
rjgoyln:feat/prek-exception-format-args
Draft

Catch format-string arguments passed to exception constructors#73076
rjgoyln wants to merge 1 commit into
apache:mainfrom
rjgoyln:feat/prek-exception-format-args

Conversation

@rjgoyln

@rjgoyln rjgoyln commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Exception constructors do not interpolate. raise AirflowException("TaskInstance %s is not found", ti.task_id) reads like a logger call, but Exception.__init__ only stores its arguments — the message keeps its literal %s, and the identifier it exists to carry sits beside it in args. Where the exception forwards just the message to super(), as google.api_core's GoogleAPICallError family does, that identifier is dropped from the message entirely.

There are 44 of these on main across seven distributions, enough for the shape to read as house style to anyone reviewing a new one. Nothing in ruff covers it: PLE1205/PLE1206 and G001/G002 are logging-only, and EM101 does fire on these lines but objects to the string literal, so taking its suggested fix leaves the bug in place.

Change

  • Add prek hook check-no-new-exception-format-args, subclassing AllowlistManager beside check-no-new-airflow-exceptions.
  • Flag a raise only when the placeholder count exactly equals the trailing-argument count, counted as Python's own % operator would consume them.
  • Record the existing 44 occurrences, which this PR does not fix.

Detection walks the AST because the pattern routinely spans several lines. The exact-count rule is what keeps the check quiet: ten or so call sites already pass a literal message alongside unrelated positional parameters — TypeError("Could not parse hits.", response), SQLAlchemy's OperationalError(statement, params, orig) — and anything looser flags all of them.


Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 5)

Generated-by: Claude Code (Opus 5) following the guidelines

Exception constructors do not interpolate their arguments the way logger
calls do, so a logging-style copy-paste leaves the placeholders in the
message and the values stranded in args. Where the exception forwards only
the message to super(), as google.api_core's does, the values are dropped
outright and the identifier the message exists to carry never reaches the
user. Nothing in ruff covers this shape, and the existing 44 occurrences
make it easy for a reviewer to read as house style.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant