Skip to content

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:

app.py
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()  # noqa

That 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:

app.py
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:

legacy.py
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.

For a contiguous region rather than one line, use range comments instead. See how to disable Ruff rules for a block of code.

Learn More

Last updated on