ruff FURB129: fix changes program behavior
Hypothesis Nemotron 3 Super predicted to fire fired 1×
If the file object is used elsewhere in the loop body (e.g., `fp.seek(0)`), switching to direct iteration may interfere with internal buffering or iteration state, causing skipped lines or infinite lo
Program
Output
(no stdout)
(no stdout)
- fired
- 1 before · 0 after
- runs
- each version twice, same file name, no network
Judge Nemotron 3 Ultra advisory real · 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.
Explanation Nemotron 3 Super unverified
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.
Reproduce
- file
prog.py(the before program)- minimized program
- r2-p002.py
- evidence sheet
- r2-p002.md
- regression fixture
- r2-p002.py the minimized program with a header stating the observed change, for the tool's test suite
python3 prog.py ruff check --preview --isolated --select FURB129 --fix prog.py python3 prog.py
Upstream search GitHub issues Tavily Nemotron 3 Super + Ultra
FURB129 fix · FURB129 readlines iteration · fp seek zero loop · file iterator replacement
- related 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 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 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 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
- program
- File Object Used Elsewhere in Loop Body
- hazard
- If the file object is used elsewhere in the loop body (e.g., `fp.seek(0)`), switching to direct iteration may interfere with internal buffering or iteration state, causing skipped lines or infinite lo
- oracle
exit 0 → timeout- run
- 2026-10-17T21-30-17-728Z-bxl4-ruff-FURB129
generated program (12 lines) and the fix's diff
--- orig.py 2026-10-17 17:30:44.966729680 -0400 +++ fixed.py 2026-10-17 17:30:45.132727007 -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: if line.strip() == '1': fp.seek(0) print(line.strip())
rule documentation given to the models
# readlines-in-for (FURB129)
Derived from the **refurb** linter.
Fix is always available.
## What it does
Checks for uses of `readlines()` when iterating over a file line-by-line.
## Why is this bad?
Rather than iterating over all lines in a file by calling `readlines()`,
it's more convenient and performant to iterate over the file object
directly.
## Example
```python
with open("file.txt") as fp:
for line in fp.readlines():
...
```
Use instead:
```python
with open("file.txt") as fp:
for line in fp:
...
```
## Fix safety
This rule's fix is marked as unsafe if there's comments in the
`readlines()` call, as comments may be removed.
For example, the fix would be marked as unsafe in the following case:
```python
with open("file.txt") as fp:
for line in ( # comment
fp.readlines() # comment
):
...
```
## References
- [Python documentation: `io.IOBase.readlines`](https://docs.python.org/3/library/io.html#io.IOBase.readlines)