# ruff G010: fix changes program behavior

Internal evidence sheet generated by fixhunt. Not an issue text. A human re-verifies, checks the duplicates
below, and writes the upstream report in their own words following the project's AI policy.

- Tool: ruff ruff 0.17.1
- Rule: G010 (tool labels the fix: unknown, this fix reported as safe)
- Oracle: fix-changes-behavior
- Judge (Nemotron 3 Ultra, advisory): real, severity medium. The rule rewrites logger.warn to logger.warning assuming the logger object has a warning method, but the program uses a custom NullLogger class that lacks both warn and warning methods. The fix changes which AttributeError is raised, altering the program's observable behavior in a way the documentation does not account for, since the heuristic matched the variable name 'logger' but the object does not conform to the logging module's interface.
- Program: minimized from 11 to 11 lines

## Reproducer

```python
DEBUG = False
class DebugLogger:
    def warn(self, msg):
        print(f'DEBUG WARN: {msg}')
class NullLogger:
    pass  # No warn or warning
logger = DebugLogger() if DEBUG else NullLogger()
try:
    logger.warn('test')
except AttributeError as e:
    print(type(e).__name__, str(e))
```

## Commands

```sh
python3 prog.py
ruff check --preview --isolated --select G010 --fix prog.py
python3 prog.py
```

## Observed

```
stdout before:
AttributeError 'NullLogger' object has no attribute 'warn'
stdout after:
AttributeError 'NullLogger' object has no attribute 'warning'
```

## Diff applied by the fix

```diff
--- orig.py	2026-10-22 13:29:03.538595835 -0400
+++ fixed.py	2026-10-22 13:29:05.602630293 -0400
@@ -6,6 +6,6 @@
     pass  # No warn or warning
 logger = DebugLogger() if DEBUG else NullLogger()
 try:
-    logger.warn('test')
+    logger.warning('test')
 except AttributeError as e:
     print(type(e).__name__, str(e))
```

## Why the rewrite is not equivalent (model draft, verify before use)

The original call uses method name `warn`, which exists only on `DebugLogger`. When `DEBUG` is false, `logger` becomes a `NullLogger` lacking `warn`, raising an `AttributeError` for missing `warn`. After rewriting to `warning`, the same `NullLogger` still lacks this method, so it raises an `AttributeError` for missing `warning`. Although both cases raise `AttributeError`, the error message differs because it reports the absent method name (`warn` vs `warning`). Since the program’s output includes this message, the change alters observable behavior, violating semantic equivalence despite both branches raising the same exception type. The fix assumes method name interchangeability, but the error message depends on the exact attribute accessed.

## Upstream search

Queries: "G010 fix", "ruff G010 method name change", "DebugLogger NullLogger warn call", "attribute error on missing method"

- duplicate: https://github.com/astral-sh/ruff/issues/14147
  Exact same bug report: DJ006 false positive on ModelForm.exclude for inherited forms.
- duplicate: https://github.com/astral-sh/ruff/issues/14147
  Duplicate of the exact same DJ006 false positive bug report on ModelForm.exclude for inherited forms.

<details><summary>All hits</summary>

- [github, open] No error on `logging.Logger.warn` access [G010] — https://github.com/astral-sh/ruff/issues/12295
- [github, open] Implement `flake8-logging` — https://github.com/astral-sh/ruff/issues/7248
- [github, open] Add support for rule aliasing — https://github.com/astral-sh/ruff/issues/2186
- [github, closed] unused-function-argument not silenced by prefixed underscore if variable name is "次" — https://github.com/astral-sh/ruff/issues/28721
- [github, closed] G rules seems not working with loguru. — https://github.com/astral-sh/ruff/issues/13673
- [github, closed] Ord violation panic when fixing file with nightly compiler — https://github.com/astral-sh/ruff/issues/12469
- [github, closed] Pack of fuzzer Autofix/Infinite loop errors [2] — https://github.com/astral-sh/ruff/issues/8402
- [github, closed] Rule RUF027 cause panic — https://github.com/astral-sh/ruff/issues/9895
- [github, closed] Fixed code unformatted — https://github.com/astral-sh/ruff/issues/8619
- [github, closed] Add option to disable preview warnings — https://github.com/astral-sh/ruff/issues/8620
- [tavily] UP035 --fix not working for quoted types · Issue #3508 · astral-sh/ruff · GitHub — https://github.com/astral-sh/ruff/issues/3508
- [tavily] Fix all can't fix "UP" violations. · Issue #670 · astral-sh/ruff-vscode · GitHub — https://github.com/astral-sh/ruff-vscode/issues/670
- [tavily] Change `--fix-only` exit semantics to mirror `--fix` by charliermarsh · Pull Request #4146 · astral-sh/ruff · GitHub — https://github.com/astral-sh/ruff/pull/4146
- [tavily] Fix `unnecessary-encode-utf8` to fix `encode` on parenthesized strings correctly by harupy · Pull Request #5478 · astral-sh/ruff · GitHub — https://github.com/astral-sh/ruff/pull/5478
- [tavily] Rule request: Warn whenever any default value is provided in __post_init__ · Issue #13128 · astral-sh/ruff · GitHub — https://github.com/astral-sh/ruff/issues/13128
- [tavily] Warn about error being related to a deprecated rule · Issue #18349 · astral-sh/ruff · GitHub — https://github.com/astral-sh/ruff/issues/18349
- [tavily] Warn about too old python-version · Issue #201 · astral-sh/ty · GitHub — https://github.com/astral-sh/ruff/issues/16094
- [tavily] `boolean-positional-value-in-call` (`FBT003`) - don't warn when function name starts with `set_` and only takes one argument · Issue #8923 · astral-sh/ruff · GitHub — https://github.com/astral-sh/ruff/issues/8923
- [tavily] Add a new rule to warn on implicitly-concatenated strings separated by a comment · Issue #13014 · astral-sh/ruff · GitHub — https://github.com/astral-sh/ruff/issues/13014
- [tavily] [formatter] Warn when markdown files are skipped due to preview being disabled by chinar-amrutkar · Pull Request #24150 · astral-sh/ruff · GitHub — https://redirect.github.com/astral-sh/ruff/pull/24150
- [tavily] Warn against quadratic list summation · Issue #5073 · astral-sh/ruff · GitHub — https://github.com/astral-sh/ruff/issues/5073
- [github, open] Implement `pydoclint` — https://github.com/astral-sh/ruff/issues/12434
- [github, open] Implement Pylint — https://github.com/astral-sh/ruff/issues/970
- [github, open] `PYI029` and `@abstractmethod` implementations — https://github.com/astral-sh/ruff/issues/18372
- [github, open] feature: Support D417 for __init__ Parameters in numpy class docstrings — https://github.com/astral-sh/ruff/issues/924
- [github, open] PLE0241 fix should be unsafe — https://github.com/astral-sh/ruff/issues/18712
- [github, open] D417 Argument descriptions only required if there is an "Args" section — https://github.com/astral-sh/ruff/issues/2310
- [github, open] DJ012 is not raised when a parent class, that inherits from django.Model, is in a different file. — https://github.com/astral-sh/ruff/issues/12865
- [github, open] PLC2801 fix ignores the expression’s syntactic context — https://github.com/astral-sh/ruff/issues/16053
- [github, open] Ruleset Suggestion: wemake-python-styleguide — https://github.com/astral-sh/ruff/issues/3845
- [github, open] DJ006 doesn't detect ModelForm.exclude on inherited forms — https://github.com/astral-sh/ruff/issues/14147
- [tavily] ruff can not run on aarch64 machine · Issue #3791 · astral-sh/ruff · GitHub — https://github.com/astral-sh/ruff/issues/3791
- [tavily] Rule request: enforce setting name=None when raising AttributeError/NameError with a custom error message on py310+ · Issue #12849 · astral-sh/ruff · GitHub — https://github.com/astral-sh/ruff/issues/12849
- [tavily] Detect `not_called()` and similar mistakes with Python mocks before Python 3.12 · Issue #13252 · astral-sh/ruff · GitHub — https://github.com/astral-sh/ruff/issues/13252

</details>
