# 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 rule removes an `if TYPE_CHECKING:` block without ensuring `TYPE_CHECKING` is imported from `typing`. In the original code, the `NameError` occurs at runtime when evaluating the condition, but the fix deletes the block entirely, silencing the error and changing the exit status from 1 to 0. The documentation presents the rewrite as a safe removal of dead code, but it is only safe when `TYPE_CHECKING` is properly defined; otherwise, it masks a pre-existing runtime failure.
- 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:54.557448373 -0400
+++ fixed.py	2026-10-22 13:29:56.642483249 -0400
@@ -1,2 +0,0 @@
-if TYPE_CHECKING:
-    pass
```

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

The original program references `TYPE_CHECKING` in a conditional; if undefined, it raises a `NameError`. Removing that block eliminates the reference entirely, so no error occurs when `TYPE_CHECKING` is absent—changing behavior from raising an exception to executing silently. This alters observable outcomes, violating semantic equivalence.

## Upstream search

Queries: "TC005 fix", "ruff TC005 if TYPE_CHECKING block", "TC005 remove unused conditional import guard", "fix behavior of empty TYPE_CHECKING blocks"

- 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
- related: https://github.com/astral-sh/ruff/issues/1785
  feature request to implement flake8-type-checking rules
- related: https://github.com/astral-sh/ruff/issues/2214
  TCH rules requiring future annotations for 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, closed] regression: ruff deletes imports; successive checks fail due to missing import — https://github.com/astral-sh/ruff/issues/14698

</details>
