| --- |
| title: Pyrefly Error Suppressions |
| |
| description: Learn how to suppress type check errors in Pyrefly with code comments and baseline files. |
| --- |
| |
| {/* |
| * Copyright (c) Meta Platforms, Inc. and affiliates. |
| * |
| * This source code is licensed under the MIT license found in the |
| * LICENSE file in the root directory of this source tree. |
| */} |
| |
| import CodeSnippet from '@site/src/sandbox/CodeSnippet' |
| |
| ## Error Suppression Comments |
| |
| The Python type system allows you to suppress errors with a comment. This feature can be helpful in many scenarios. For example, after enabling a type checker, suppressions can allow you to get a clean type check signal without having to stop and fix every pre-existing error in your code. |
| |
| There are multiple ways to do this in Pyrefly. |
| |
| ```python |
| def foo() -> int: |
| # pyrefly: ignore |
| return "this is a type error" |
| ``` |
| |
| You can also put the comment on the same line as the error. |
| |
| ```python |
| def foo() -> int: |
| return "this is a type error" # pyrefly: ignore |
| ``` |
| |
| You can also target specific error types: |
| |
| ```python |
| def foo() -> int: |
| return "this is a type error" # pyrefly: ignore[bad-return] |
| ``` |
| |
| We respect the specification and allow `type: ignore` to be used: |
| |
| ```python |
| def foo() -> int: |
| return "this is a type error" # type: ignore |
| ``` |
| |
| |
| We also have a special comment that will ignore all errors in a file. |
| |
| |
| <pre> |
| <CodeSnippet |
| sampleFilename="why_hints.py" |
| isCodeSnippet={true} |
| codeSample={`# pyrefly: ignore-errors |
| |
| from typing import * |
| |
| def test(x: int): |
| return f"{x}" |
| |
| def bar() -> int: |
| # this error won't be reported |
| return "" |
| `} |
| /> |
| </pre> |
| |
| To ignore one error type across a file, add the error code to the file-level comment: |
| |
| ```python |
| # pyrefly: ignore-errors[bad-assignment] |
| ``` |
| |
| A file-level `ignore-errors` / `ignore-errors[code]` directive is only honored when it |
| appears at the beginning of the file, before any code (comments, blank lines, and the |
| module docstring may precede it). Placed after the first line of code it is silently |
| inert — it suppresses nothing — and Pyrefly reports a |
| [`misplaced-ignore`](../error-kinds#misplaced-ignore) warning pointing at it. To suppress |
| errors past the top of a file, use a line-level `# pyrefly: ignore[code]` instead. |
| |
| Pyrefly can automatically suppress all type errors in your project by running: |
| |
| ``` |
| pyrefly suppress |
| ``` |
| |
| This is equivalent to `pyrefly check --suppress-errors`. |
| |
| By default, `pyrefly suppress` places suppression comments on the line before the error. If you use other tools that also add comments on the line before (e.g. linters, other type checkers), their suppression comments may conflict with each other. To reduce conflicts, you can use `--comment-location=same-line` to place Pyrefly's suppression comments as trailing comments on the same line as the error: |
| |
| ``` |
| pyrefly suppress --comment-location=same-line |
| ``` |
| |
| ## Baseline Files (Experimental) |
| |
| Pyrefly also supports storing errors in a baseline file. Any errors matching the baseline will be ignored and only new errors will be reported. |
| This is useful when introducing type checking to a project for the first time, or when rolling out changes that require many suppression comments. |
| This feature is inspired by tools like [basedpyright](https://docs.basedpyright.com/latest/benefits-over-pyright/baseline/) and [Android Studio](https://developer.android.com/studio/write/lint#snapshot). |
| A baseline is the recommended starting point when migrating a large codebase from [mypy](./migrate/mypy/index.mdx) or [Pyright](./migrate/pyright/index.mdx). |
| |
| To generate (or re-generate) the baseline file: |
| |
| ``` |
| pyrefly check --baseline="<path to baseline file>" --update-baseline |
| ``` |
| |
| To check your project using a baseline file and report only newly-introduced errors, you can either use the CLI flag: |
| |
| ``` |
| pyrefly check --baseline="<path to baseline file>" |
| ``` |
| |
| Or specify the baseline in your configuration file (`pyrefly.toml` or `pyproject.toml`): |
| |
| ```toml |
| # pyrefly.toml |
| baseline = "baseline.json" |
| ``` |
| |
| ```toml |
| # pyproject.toml |
| [tool.pyrefly] |
| baseline = "baseline.json" |
| ``` |
| |
| When the baseline is specified in the configuration file, you don't need to pass the `--baseline` flag on every invocation. The CLI flag takes precedence if both are specified. |
| |
| Note that `baseline` is a **project-level setting** and cannot be overridden in [`sub-config`](./configuration.mdx#sub-configs) sections. If you need different baseline files for different parts of your codebase, consider using separate Pyrefly configuration files. |
| |
| Errors are matched with the baseline by looking at file, error code, and column number. |
| Note that errors suppressed by the baseline file are still shown in the IDE. |
| |
| `--baseline-error-level=<ignore|info|warn|error>` and the project-level |
| `baseline-error-level` setting control how matching errors are reported. The |
| default is `ignore`, which omits them from CLI output; the other levels emit them |
| at a reduced or unchanged severity: |
| |
| ```toml |
| baseline = "baseline.json" |
| baseline-error-level = "warn" |
| ``` |
| |
| Emitted matches follow the normal `--min-severity` filtering and exit-status rules. |
| Pyrefly records baseline provenance differently depending on the output format: |
| |
| - `full-text` and `min-text`: matched findings include `[baselined]` after the error-kind marker. |
| - `github`: matched findings include `[baselined]` in the annotation title. |
| - `json`: when a baseline is configured, each result has `baselined` set to `true` for a match and `false` otherwise. |
| - `sarif`: when a baseline is configured, each result has `baselineState` set to `unchanged` for a match and `new` otherwise. |
| - `omit-errors`: the summary includes the number of emitted baselined diagnostics. |
| |
| If a baseline file is configured but cannot be read or parsed, the run fails with an error rather than proceeding as if no baseline were set. The exception is `--update-baseline`, which regenerates the file from scratch and so tolerates a missing or unparseable baseline. |
| |
| As you fix errors, the entries that suppressed them become stale. Two flags help keep the baseline current: |
| |
| ``` |
| # Rewrite the baseline to drop stale entries, without recording any new errors. |
| pyrefly check --prune-baseline |
| |
| # Exit with a non-zero status if the baseline contains stale entries. |
| pyrefly check --error-stale-baseline |
| ``` |
| |
| Both actions use the scope of the current check. An unmatched entry is stale when its file was checked, or when the file is confirmed not to exist. Entries for existing files outside a narrowed check are retained, as are entries whose file status cannot be determined because of a filesystem error. |
| |
| Pruning keeps entries for diagnostics that still occur, even when `--min-severity` hides them. This is intentionally conservative. `--update-baseline` instead regenerates the baseline from diagnostics at or above the severity threshold. |
| |
| `--error-stale-baseline` is intended for CI, where an out-of-date baseline should fail the build the same way a new error does. `--prune-baseline`, `--error-stale-baseline`, and `--update-baseline` are mutually exclusive, and each requires a baseline file from `--baseline` or the configuration file. |
| |
| This feature is experimental, so please submit any feedback or requests you have on our Github repo. |
| |
| ## Upgrading Pyrefly (And other changes that introduce new type errors) |
| |
| Upgrading the version of Pyrefly you're using, or a third party library you depend on can surface new type errors in your code. Fixing them all at once is often not realistic. We've written scripts to help you temporarily silence them. |
| |
| ``` |
| # step 1 |
| pyrefly suppress |
| ``` |
| |
| ``` |
| # step 2 |
| <run your formatter of choice> |
| ``` |
| |
| ``` |
| # step 3 |
| pyrefly suppress --remove-unused |
| ``` |
| Repeat the steps above until you get a clean formatting run and a clean type check. |
| |
| This will add ` # pyrefly: ignore` comments to your code that will enable you to silence errors, and come back and fix them at a later date. This can make the process of upgrading a large codebase much more manageable. |
| |
| By default, `--remove-unused` removes Pyrefly and Pyre ignores and preserves `# type: ignore` comments because they may be shared with other type checkers. `--remove-unused=pyrefly` is equivalent to the bare flag. Use `pyrefly suppress --remove-unused=type` to remove only unused `# type: ignore` comments, or `pyrefly suppress --remove-unused=all` to remove all three kinds. |
| |
| :::tip |
| If your project uses other tools that place suppression comments on the line before the error (e.g. other type checkers or linters), use `pyrefly suppress --comment-location=same-line` in step 1 to avoid conflicts. |
| ::: |
| |
| :::note |
| `pyrefly suppress` is equivalent to `pyrefly check --suppress-errors`, and `pyrefly suppress --remove-unused[=KIND]` is equivalent to `pyrefly check --remove-unused-ignores[=KIND]`. |
| ::: |