# ruff W605: 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: W605 (tool labels the fix: unknown, this fix reported as safe)
- Oracle: fix-changes-behavior
- Judge (Nemotron 3 Ultra, advisory): intended-change, severity low. The rule rewrites the invalid escape sequence '\.' into a raw string r'\.' to eliminate the SyntaxWarning, which is exactly the documented purpose. The program's output changes because the warning disappears, demonstrating the rule did what it documents.
- Program: minimized from 7 to 4 lines

## Reproducer

```python
s = '\.' 'rest'
t = s
if '__' in t:
    print('single backslash')
```

## Commands

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

## Observed

```
stderr before: /w/prog.py:1: SyntaxWarning: invalid escape sequence '\.'
stderr after: (none)
```

## Diff applied by the fix

```diff
--- orig.py	2026-10-22 13:31:55.493475211 -0400
+++ fixed.py	2026-10-22 13:31:57.586510355 -0400
@@ -1,4 +1,4 @@
-s = '\.' 'rest'
+s = r'\.' 'rest'
 t = s
 if '__' in t:
     print('single backslash')
```

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

The original string literal `'\.'` contains an invalid escape sequence `\.` which Python treats as two characters: backslash followed by dot, while issuing a SyntaxWarning. After rewriting to `r'\.'`, it becomes a raw string where `\.` is interpreted literally as backslash-dot without warning. Although both evaluate to the same two-character string `'\\.'`, the change eliminates the SyntaxWarning that was present in the original program’s stderr output. Since the fix alters observable behavior—specifically, removing a diagnostic message—the transformation is not semantics-preserving under the criterion that includes all program outputs, including warnings. Thus, labeling the fix as "safe" is incorrect because it changes what the program emits during execution.

## Upstream search

Queries: "W605 fix", "invalid escape sequence dot", "W605 raw string recommendation", "backslash literal warning"

- related: https://github.com/astral-sh/ruff/issues/11491
  Both involve W605 autofix changing behavior, but the existing report is about f-strings while the new finding is about implicit string concatenation.
- related: https://github.com/astral-sh/ruff/issues/19655
  Both involve W605 autofix issues, but the existing report is about interaction with ISC002 on multi-line strings, while the new finding is about implicit concatenation on a single line.
- duplicate: https://github.com/astral-sh/ruff/issues/11461
  The existing report is titled 'W605 fix is unsafe' and describes the autofix changing behavior by adding a raw prefix to a string with an invalid escape sequence, which is exactly the same defect on the same construct (implicit string concatenation with an invalid escape).
- related: https://github.com/astral-sh/ruff/issues/10434
  Both involve W605 causing issues with autofix, but the existing report is about a panic/crash on f-strings, while the new finding is about a silent behavior change on implicit concatenation.
- related: https://github.com/astral-sh/ruff/issues/6987
  Both involve W605 autofix errors, but the existing report mentions ANN401 and W605 causing autofix errors generally, not the specific behavior change on implicit concatenation.
- related: https://github.com/astral-sh/ruff/issues/5061
  This is a feature request to use raw strings for W605 fixes, which is what the autofix does in the new finding, but the request doesn't describe the behavior-change defect.
- related: https://github.com/astral-sh/ruff/issues/20151
  Both involve autofix changing behavior (G004 vs W605), but the existing report is about G004 on a different construct.
- related: https://github.com/astral-sh/ruff/issues/20196
  Both involve W605 and invalid escape sequences, but the existing report is about auditing CPython SyntaxWarning parity, not the autofix behavior change.

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

- [github, open] Wrong fix for W605 in f-strings — https://github.com/astral-sh/ruff/issues/11491
- [github, open] Implement remaining `pycodestyle` rules — https://github.com/astral-sh/ruff/issues/2402
- [github, open] Include some of the checks from flake8-literal — https://github.com/astral-sh/ruff/issues/8616
- [github, closed] unused-function-argument not silenced by prefixed underscore if variable name is "次" — https://github.com/astral-sh/ruff/issues/28721
- [github, open] Implement Pylint — https://github.com/astral-sh/ruff/issues/970
- [github, closed] ISC002 makes W605 unfixable on playground — https://github.com/astral-sh/ruff/issues/19655
- [github, closed] W605 fix is unsafe — https://github.com/astral-sh/ruff/issues/11461
- [github, closed] Ruff does not clean up unused import if it has same name like object attribute — https://github.com/astral-sh/ruff/issues/12775
- [github, closed] Pack of fuzzer Autofix/Infinite loop errors [2] — https://github.com/astral-sh/ruff/issues/8402
- [github, closed] Rule W605 cause panic — https://github.com/astral-sh/ruff/issues/10434
- [tavily] Rules ANN401,W605 cause autofix error · Issue #6987 · astral-sh/ruff · GitHub — https://github.com/astral-sh/ruff/issues/6987
- [tavily] Change W605 autofix to use raw strings if possible · Issue #5061 · astral-sh/ruff · GitHub — https://github.com/astral-sh/ruff/issues/5061
- [github, open] Ruleset Suggestion: wemake-python-styleguide — https://github.com/astral-sh/ruff/issues/3845
- [github, closed] Isort rule misses unsorted imports when using user-level ruff.toml file on windows — https://github.com/astral-sh/ruff/issues/19646
- [github, closed] [QA] Should Ruff be able to fix indentation errors (E999) ? — https://github.com/astral-sh/ruff/issues/11846
- [tavily] G004 fix can change behavior and introduce syntax errors · Issue #20151 · astral-sh/ruff · GitHub — https://github.com/astral-sh/ruff/issues/20151
- [tavily] Q000 fixer does not remove obsolete backslash-escape inside string after changing quotes · Issue #8617 · astral-sh/ruff · GitHub — https://github.com/astral-sh/ruff/issues/8617
- [tavily] Surrogate code points are internally represented as U+FFFD REPLACEMENT CHARACTER · Issue #13666 · astral-sh/ruff · GitHub — https://github.com/astral-sh/ruff/issues/13666
- [tavily] Feature: Port Sonar's Python scanner checks · Issue #4935 · astral-sh/ruff · GitHub — https://github.com/astral-sh/ruff/issues/4935
- [github, open] per-file-ignores have inconsistent behavior in symlinked directories — https://github.com/astral-sh/ruff/issues/6480
- [tavily] Ruff should warn on all CPython SyntaxWarnings · Issue #20196 · astral-sh/ruff · GitHub — https://github.com/astral-sh/ruff/issues/20196

</details>
