ruff FURB103: fix changes program behavior
Hypothesis Nemotron 3 Super predicted to fire fired 1×
If the write call is guarded by a short-circuiting expression (e.g., cond and f.write(s)), the fix hoists it unconditionally.
Program
Output
''
'should not happen'
- fired
- 1 before · 0 after
- runs
- each version twice, same file name, no network
Judge Nemotron 3 Ultra advisory real · high
The rule rewrites a guarded write (`flag and f.write(...)`) inside a `with open` block to an unguarded `Path.write_text(...)`, removing the conditional that prevented the write when `flag` is False. The documentation presents the rewrite as equivalent for writing a single string, but does not account for conditional writes, so the fix changes program behavior silently.
Explanation Nemotron 3 Super unverified
The original condition `flag and f.write(...)` short‑circuits because `flag` is `False`, so `f.write` is never called; the file remains empty. The replacement unconditionally writes `'should not happen'` via `pathlib.Path.write_text`, creating content that did not exist before, thus changing the program’s output from an empty string to `'should not happen'`. This alters observable behavior, violating semantic equivalence.
Reproduce
- file
prog.py(the before program)- minimized program
- r1-p006.py
- evidence sheet
- r1-p006.md
- regression fixture
- r1-p006.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 FURB103 --fix prog.py python3 prog.py
Upstream search GitHub issues Tavily Nemotron 3 Super + Ultra
FURB103 fix · FURB103 short-circuit logical expression · FURB103 boolean flag file write · FURB103 conditional file operation
- duplicate astral-sh/ruff/issues/29452 same rule FURB103 dropping the surrounding expression (flag and ...) when rewriting a conditional write to Path.write_text
- related astral-sh/ruff/issues/26920 same rule FURB103 but different defect: truncation semantics vs. dropped conditional expression
- related astral-sh/ruff/issues/26922 same rule family FURB101/FURB103 but different defect: runtime errors from safe fixes vs. dropped conditional expression
- related astral-sh/ruff/issues/21483 same rule FURB103 but different defect: variable used later vs. dropped conditional expression
- related astral-sh/ruff/issues/18409 same rule FURB103 but different context: encoding/path.open suggestion vs. dropped conditional expression
- related astral-sh/ruff/issues/20785 same rule FURB103 but different defect: json.dumps serialization breakage vs. dropped conditional expression
Details
- program
- Short-circuiting expression guards write
- hazard
- If the write call is guarded by a short-circuiting expression (e.g., cond and f.write(s)), the fix hoists it unconditionally.
- oracle
stdout before: '' stdout after: 'should not happen'- run
- 2026-10-17T19-38-23-545Z-dfhv-ruff-FURB103
generated program (6 lines) and the fix's diff
--- orig.py 2026-10-17 15:38:33.452462839 -0400 +++ fixed.py 2026-10-17 15:38:33.605460950 -0400 @@ -1,6 +1,6 @@ +import pathlib flag = False -with open('s.txt', 'w') as f: - flag and f.write('should not happen') +pathlib.Path('s.txt').write_text('should not happen') with open('s.txt', 'r') as f: print(repr(f.read())) import os; os.remove('s.txt')
rule documentation given to the models
# write-whole-file (FURB103)
Derived from the **refurb** linter.
Fix is sometimes available.
This rule is in preview and is not stable. The `--preview` flag is required for use.
## What it does
Checks for uses of `open` and `write` that can be replaced by `pathlib`
methods, like `Path.write_text` and `Path.write_bytes`.
## Why is this bad?
When writing a single string to a file, it's simpler and more concise
to use `pathlib` methods like `Path.write_text` and `Path.write_bytes`
instead of `open` and `write` calls via `with` statements.
## Example
```python
with open("file.txt", "w") as f:
f.write("some text")
```
Use instead:
```python
from pathlib import Path
Path("file.txt").write_text("some text")
```
## Fix Safety
This rule's fix is marked as unsafe if the replacement would remove comments attached to the original expression.
## References
- [Python documentation: `Path.write_bytes`](https://docs.python.org/3/library/pathlib.html#pathlib.Path.write_bytes)
- [Python documentation: `Path.write_text`](https://docs.python.org/3/library/pathlib.html#pathlib.Path.write_text)