ruff FURB103: fix changes program behavior
Hypothesis Nemotron 3 Super predicted to fire fired 1×
Ignores custom openers or file descriptors passed via opener=, which Path.write_text does not support.
Program
Output
(no stdout) OSError: [Errno 9] Bad file descriptor
(no stdout) TypeError: argument should be a str or an os.PathLike object where __fspath__ returns a str, not 'int'
- fired
- 1 before · 0 after
- runs
- each version twice, same file name, no network
- minimizer
- 29 oracle evaluations
Judge Nemotron 3 Ultra advisory program-bug · low
The original program already fails with OSError: [Errno 9] Bad file descriptor because os.open returns an integer file descriptor, but the built-in open() function expects a path string or path-like object, not a raw file descriptor. The fix changes the error to a TypeError from pathlib.Path, but the program was already broken before the rewrite due to incorrect usage of os.open with open().
Explanation Nemotron 3 Super unverified
The original code opens a file via `os.open`, obtaining an integer file descriptor (`fd`), then uses it directly in `open(fd, 'w')` to create a text stream for writing—this is valid because Python’s built-in `open()` accepts integer file descriptors. The rewrite replaces this with `pathlib.Path(fd).write_text(...)`, but `Path` expects a string or path-like object (e.g., filename), not an integer file descriptor. Passing an `int` to `Path()` raises a `TypeError` because integers do not implement `__fspath__`. Thus, the rewrite fails at runtime where the original succeeded, altering behavior from successful file write to immediate exception. This violates semantic preservation: the fix changes what the program does, not just how it does it. The label “safe” is incorrect—the transformation assumes `fd` is a path, but it is a descriptor, making the rewrite invalid for this use case. No speculation about the tool is needed; the error arises directly from mismatched types.
Reproduce
- file
prog.py(the before program)- minimized program
- r1-p009.py
- evidence sheet
- r1-p009.md
- regression fixture
- r1-p009.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 os.open file descriptor usage · ruff FURB103 Path.write_text integer argument · FURB103 replace os.open with pathlib
no duplicate or related report 6 hits triaged
Details
- program
- FURB103 Hazard 9: Custom Opener Ignored
- hazard
- Ignores custom openers or file descriptors passed via opener=, which Path.write_text does not support.
- oracle
stderr before: OSError: [Errno 9] Bad file descriptor stderr after: TypeError: argument should be a str or an os.PathLike object where __fspath__ returns a str, not 'int'- run
- 2026-10-27T22-10-17-844Z-aav5-ruff-FURB103
generated program (9 lines) and the fix's diff
--- orig.py 2026-10-27 22:10:36.039629052 +0000 +++ fixed.py 2026-10-27 22:10:39.566823810 +0000 @@ -1,9 +1,9 @@ import os +import pathlib # Use fd 3 via dup fd = os.open('custom.txt', os.O_WRONLY | os.O_CREAT | os.O_TRUNC) os.set_inheritable(fd, True) -with open(fd, 'w') as f: - f.write('via fd') +pathlib.Path(fd).write_text('via fd') os.close(fd) with open('custom.txt') as f: print(repr(f.read()))
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)