How to Suppress a Ruff Warning on One Line
Ruff flags a line that cannot be fixed right now: a legacy call site, a deliberate exception, a pattern the rule cannot see the reason for. A # noqa comment silences that one rule on that one line, leaving every other line under enforcement.
Read the Rule Code From Ruff’s Output
Every diagnostic starts with the code to suppress. Run the linter and read it off the report:
uv run ruff check --output-format concise .uv run executes the command inside the project’s virtual environment, ensuring all dependencies are installed first.
app.py:5:12: SIM115 Use a context manager for opening files
Found 1 error.SIM115 is the code. The Ruff rule codes explainer covers what the prefixes mean.
Append the Code to the Offending Line
Put # noqa: CODE at the end of the line the diagnostic points at:
import json
def load(path):
data = open(path).read() # noqa: SIM115
return json.loads(data)Re-run the linter to confirm:
uv run ruff check --output-format concise .All checks passed!The comment has to sit on the same physical line as the violation. For a multi-line string, put it after the closing triple quote, where it applies to the whole string.
To silence more than one rule, separate the codes with commas: # noqa: SIM115, E501.
Always Name the Code
A bare # noqa suppresses every rule on the line, including rules that start firing there later:
data = open(path).read() # noqaThat comment hides SIM115 today and hides whatever else lands on the line tomorrow. The targeted form fails loudly instead: if SIM115 stops firing, Ruff tells you the comment is dead.
Let RUF100 Delete Stale Suppressions
Rewrite load to use a context manager and the suppression becomes dead weight:
def load(path):
with open(path) as f: # noqa: SIM115
return json.loads(f.read())RUF100 (unused-noqa) is in Ruff’s default rule set, so it catches that with no configuration:
app.py:5:28: RUF100 [*] Unused `noqa` directive (unused: `SIM115`)
Found 1 error.
[*] 1 fixable with the `--fix` option.Ruff removes the comment itself:
uv run ruff check --fix .Found 1 error (1 fixed, 0 remaining).The # noqa: SIM115 comment is gone from the file. Suppressions stay tied to violations that actually exist rather than accumulating as scar tissue.
Freeze Existing Violations in Bulk
Turning on a new rule across an old codebase produces hundreds of diagnostics at once. --add-noqa writes the comments for you, so the rule can be enforced on new code starting today:
uv run ruff check --add-noqa .Added 2 noqa directives.Each violating line gains its own targeted comment:
import json
def save(path, obj):
handle = open(path, "w") # noqa: SIM115
handle.write(json.dumps(obj))Commit that as a separate change, then work the suppressions down over time. RUF100 keeps score as each one becomes unnecessary.
Choose Between noqa and Ruff’s Native Comment
Ruff also accepts its own syntax, # ruff: ignore[CODE], with --add-ignore as the bulk equivalent. Both forms suppress the same way and both are cleaned up by RUF100.
# noqa: SIM115 |
# ruff: ignore[SIM115] |
|
|---|---|---|
| Understood by flake8 and its plugins | Yes | No |
| Behavior with no codes listed | Suppresses every rule on the line | Suppresses nothing |
Prefer # noqa while any flake8-based tooling still reads the file, and for the familiarity of a syntax the wider ecosystem already shares. The native form is the safer default in a Ruff-only codebase, because the degenerate case fails closed.
Learn More
- Ruff error suppression
- RUF100: unused-noqa
- lint.per-file-ignores setting suppresses a rule across whole paths rather than single lines
- How to configure recommended Ruff defaults