# ruff TC005: 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: TC005 (tool labels the fix: unknown, this fix reported as safe)
- Oracle: fix-changes-behavior
- Judge (Nemotron 3 Ultra, advisory): real, severity high. The fix removes the entire `if TYPE_CHECKING:` block, but the program does not import `TYPE_CHECKING` from `typing`. Before the fix, the block raises a `NameError` at runtime; after the fix, the program runs silently. The documentation presents the rewrite as a safe removal of dead code, assuming `TYPE_CHECKING` is defined, so the fix changes behavior for plausible code that omits the import.
- Program: minimized from 5 to 2 lines

## Reproducer

```python
if TYPE_CHECKING:
    pass
```

## Commands

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

## Observed

```
exit 1 → 0
stderr before: NameError: name 'TYPE_CHECKING' is not defined
stderr after: (none)
```

## Diff applied by the fix

```diff
--- orig.py	2026-10-22 13:29:42.355244323 -0400
+++ fixed.py	2026-10-22 13:29:44.393278397 -0400
@@ -1,2 +0,0 @@
-if TYPE_CHECKING:
-    pass
```

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

The original program defines `pass` inside an `if TYPE_CHECKING:` block that never executes because `TYPE_CHECKING` is undefined at runtime, so defining it has no effect; removing the block eliminates this harmless but syntactically valid definition, changing nothing observable—yet the error arises because the name `TYPE_CHECKING` is referenced in the condition, which fails when undefined. The fix deletes the reference, avoiding the NameError, thus altering runtime behavior by suppressing an exception that would otherwise occur. This changes semantics: the original program errors; the fixed version does not. Hence, the rewrite is not semantics-preserving.

## Upstream search

Queries: "TC005 fix", "TC005 if TYPE_CHECKING block", "ruff TC005 conditional import guard", "fix unused TYPE_CHECKING condition"

- duplicate: https://github.com/astral-sh/ruff/issues/28868
  same TC005 empty-type-checking-block fixer removing an if TYPE_CHECKING: pass block
- related: https://github.com/astral-sh/ruff/issues/15681
  TC003/TC002/TC001 false positives on manual TYPE_CHECKING with __future__.annotations, same rule family but different construct
- related: https://github.com/astral-sh/ruff/issues/2214
  TCH rules requiring __future__.annotations, same TYPE_CHECKING domain but different runtime behavior issue
- related: https://github.com/astral-sh/ruff/issues/17555
  identical import inside/outside TYPE_CHECKING not emitting F811, same TYPE_CHECKING context but different rule
- related: https://github.com/astral-sh/ruff/issues/9472
  lone unused import in if-statement autofix removing block, similar empty-block removal but for imports not TYPE_CHECKING
- related: https://github.com/astral-sh/ruff/issues/13929
  detect empty conditional statements after refactoring, same empty-block problem but broader than TYPE_CHECKING

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

- [github, open] TC004 runtime-import-in-type-checking-block fixer causes follow up: TC005 empty-type-checking-block + F401 unused-import + I001 unsorted-imports — https://github.com/astral-sh/ruff/issues/28868
- [github, closed] unused-function-argument not silenced by prefixed underscore if variable name is "次" — https://github.com/astral-sh/ruff/issues/28721
- [github, closed] Ruff Server errors when using a VSCode interactive session — https://github.com/astral-sh/ruff/issues/11851
- [github, closed] TC003/TC002/TC001 False positive on manual `TYPE_CHECKING` with `__future__.annotations` — https://github.com/astral-sh/ruff/issues/15681
- [github, closed] `TC006` in `0.8.1` is too broad — https://github.com/astral-sh/ruff/issues/14676
- [github, closed] Implement flake8-type-checking — https://github.com/astral-sh/ruff/issues/1785
- [tavily] Can "Unknown rule selector" be a warning, rather than an error? · Issue #5159 · astral-sh/ruff · GitHub — https://github.com/astral-sh/ruff/issues/5159
- [github, closed] TCH rules require from __future__ import annotations — https://github.com/astral-sh/ruff/issues/2214
- [github, open] PLR6301 doesn't detect @override from TYPE_CHECKING — https://github.com/astral-sh/ruff/issues/24713
- [github, open] Support and lints for `lazy` imports in Python 3.15+ — https://github.com/astral-sh/ruff/issues/21305
- [github, closed] Identical import inside+outside of `TYPE_CHECKING` block does not emit `F811` — https://github.com/astral-sh/ruff/issues/17555
- [github, closed] Lone unused import in if-statement should not get autofixed, or the if-statement should removed — https://github.com/astral-sh/ruff/issues/9472
- [github, closed] Detect empty conditional statements — https://github.com/astral-sh/ruff/issues/13929
- [github, closed] Automatically add `pragma: no cover` for `TYPE_CHECKING` blocks — https://github.com/astral-sh/ruff/issues/13610
- [github, closed] Don't move imports under `if TYPE_CHECKING` if they're added to `__all__` — https://github.com/astral-sh/ruff/issues/6236

</details>
