# ruff FURB129: 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: FURB129 (tool labels the fix: unknown, this fix reported as safe)
- Oracle: fix-changes-behavior
- Judge (Nemotron 3 Ultra, advisory): real, severity high. The fix replaces `fp.readlines()` with `fp`, changing iteration from a pre-read list to a live file iterator. The loop body calls `fp.seek(0)`, which resets the file position on each iteration. With `readlines()`, this safely re-reads the same lines from the start; with the direct iterator, it creates an infinite loop because the iterator never exhausts, causing the observed timeout.
- Program: minimized from 12 to 8 lines

## Reproducer

```python
def main():
    with open('tmp.txt', 'w') as f:
        f.write('0\n1\n2')
    with open('tmp.txt') as fp:
        for line in fp.readlines():
                fp.seek(0)
if __name__ == '__main__':
    main()
```

## Commands

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

## Observed

```
exit 0 → timeout
```

## Diff applied by the fix

```diff
--- orig.py	2026-10-22 13:42:58.920514025 -0400
+++ fixed.py	2026-10-22 13:43:00.849129736 -0400
@@ -2,7 +2,7 @@
     with open('tmp.txt', 'w') as f:
         f.write('0\n1\n2')
     with open('tmp.txt') as fp:
-        for line in fp.readlines():
+        for line in fp:
                 fp.seek(0)
 if __name__ == '__main__':
     main()
```

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

The original reads all lines into a list via readlines() before iterating; during iteration, each seek(0) resets the file pointer to the start, but since the loop operates on the pre-loaded list, it iterates exactly three times (for '0\n', '1\n', '2'), then exits. The rewritten version iterates directly over the file object fp, which yields lines lazily. Each seek(0) inside the loop resets fp to the beginning before the next line is read, causing the iterator to repeatedly yield the first line '0\n' indefinitely, resulting in an infinite loop and timeout. Thus, the change alters control flow from finite to non-terminating.

## Upstream search

Queries: "FURB129 fix", "FURB129 readlines iteration", "fp seek zero loop", "file iterator replacement"

- related: https://github.com/astral-sh/ruff/issues/18843
  Same FURB129 rule but defect is comment deletion during rewrite, not an infinite loop caused by seek inside the loop.
- related: https://github.com/astral-sh/ruff/issues/17683
  Same FURB129 rule but defect is missing whitespace after rewrite, not an infinite loop caused by seek inside the loop.
- related: https://github.com/astral-sh/ruff/issues/18231
  Same FURB129 rule but defect is syntax error with parenthesized file variable, not an infinite loop caused by seek inside the loop.
- related: https://github.com/astral-sh/ruff/issues/8402
  Meta-issue collecting autofix infinite-loop errors; the new finding is another instance of that class but not the same specific construct.

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

- [github, closed] unused-function-argument not silenced by prefixed underscore if variable name is "次" — https://github.com/astral-sh/ruff/issues/28721
- [github, closed] [`refurb`] `FURB129` fix can delete comments — https://github.com/astral-sh/ruff/issues/18843
- [github, closed] FURB129 fix should add spaces between tokens — https://github.com/astral-sh/ruff/issues/17683
- [github, closed] FURB129 fix fails when the variable is parenthesized — https://github.com/astral-sh/ruff/issues/18231
- [github, closed] Pack of fuzzer Autofix/Infinite loop errors [2] — https://github.com/astral-sh/ruff/issues/8402
- [github, open] Suggestion: Implement Sourcery rules — https://github.com/astral-sh/ruff/issues/11060
- [github, open] Implement Pylint — https://github.com/astral-sh/ruff/issues/970
- [github, open] Feature: Port Sonar's Python scanner checks — https://github.com/astral-sh/ruff/issues/4935
- [github, closed] Rule D215 cause panic `Prefer Fix::deletion` in debug build — https://github.com/astral-sh/ruff/issues/7619
- [github, closed] ruff panics in debug_assert 'Prefer `Fix::deletion`' when fixing bokeh with `--select ALL` — https://github.com/astral-sh/ruff/issues/4194
- [github, closed] UP035 vs. flake8-pep585 — https://github.com/astral-sh/ruff/issues/3388
- [github, closed] [Linter panic] so-vits-svc-fork-main\src\so_vits_svc_fork\modules\mel_processing.py — https://github.com/astral-sh/ruff/issues/4363

</details>
