Open-Source Wikis

/

Ruff

/

How to contribute

/

Debugging

astral-sh/ruff

Debugging

Notes on triaging the most common failure modes when developing on Ruff or ty.

Logging

Ruff and ty both use tracing for structured logs. Common envelope:

RUST_LOG=ruff=debug cargo run -p ruff -- check path/to/file.py
RUST_LOG=ty=debug    cargo run --bin ty -- check path/to/file.py
RUST_LOG=ty_python_semantic=trace cargo run --bin ty -- check path/to/file.py

Crate-scoped filters keep noise down. The CLIs also expose -v/-vv/-vvv flags that map to log levels.

For LSP debugging, both ruff_server and ty_server log to a configurable log file (set via the language client).

cargo dev helpers

crates/ruff_dev is the internal CLI; binary name cargo dev (i.e. cargo run -p ruff_dev --):

Command What it does
cargo dev print-ast <file> Pretty-prints the parsed AST.
cargo dev print-tokens <file> Tokenizer output for a file.
cargo dev print-cst <file> Concrete syntax tree (with trivia).
cargo dev round-trip <file> Parse → unparse → reparse and check equivalence.
cargo dev format-dev Runs the formatter against the project's curated corpus.
cargo dev generate-all Regenerates schemas, rule docs, CLI reference.

These are the first stop when a parser/formatter test fails: print the AST and compare against expectations.

Common errors

Parser

ruff_python_parser::ParseError — the parser is permissive but will still error on truly broken code. The error message includes the source range; pair with cargo dev print-tokens to see what the lexer produced just before the error.

Linter

A rule reports the wrong span: the rule's ranged() method probably returns the wrong AST node. Double-check the TextRange math; ruff_text_size ranges are byte offsets, not characters.

A rule fires on stub files when it shouldn't: check whether the rule's applicable_to or is_stub guards exclude .pyi. Many rules opt out of stubs.

A noqa comment doesn't suppress: crates/ruff_linter/src/noqa.rs parses # noqa[code] and # noqa: code,code syntax. Use cargo dev print-noqa <file> (where available) or add a debug log to inspect what was parsed.

Formatter

The formatter changed output unexpectedly: this often shows up as a flood of snapshot updates. Use cargo dev format-dev --stability-check to check that two passes produce the same output. The crates/ruff_python_formatter/CHANGELOG.md and the Black-compat tracker call out intentional divergences.

ty / Salsa

A query result seems stale or the type checker doesn't react to file edits: most likely a method that touches .node() is missing #[salsa::tracked]. From AGENTS.md: "Any method that accesses .node() must be #[salsa::tracked], or it will break incrementality."

A panic deep inside Salsa: enable backtraces (RUST_BACKTRACE=1). Also check whether the panicking function is invoked from a tracked context — if it is, returning an error variant rather than panicking is preferable.

mdtest fails locally with no obvious diff: re-run with MDTEST_UPDATE_SNAPSHOTS=1 to overwrite the inline expectations, then git diff the Markdown file.

Diagnostics rendering

When a diagnostic looks wrong (mis-aligned snippets, missing colors), the renderer is crates/ruff_annotate_snippets. Useful flags:

ruff check --output-format text ...      # default
ruff check --output-format concise ...   # one line per diagnostic
ruff check --output-format json ...      # machine-readable
ruff check --output-format github ...    # for CI annotations
ruff check --output-format sarif ...

If a span is off-by-one in concise but right in text, suspect the text/byte mapping in ruff_source_file.

Cache

Ruff caches per-file lint and format results in .ruff_cache/. To force re-execution while debugging:

ruff check --no-cache ...
rm -rf .ruff_cache

ty doesn't have an on-disk cache yet; its incremental story is Salsa-based, in-process. To start from scratch in tests, simply re-run.

Memory and performance

crates/ruff_memory_usage instruments allocation tracking; crates/ruff_benchmark runs criterion benchmarks. To run benches:

cargo bench -p ruff_benchmark

crates/ty_completion_bench and crates/ty_completion_eval benchmark and evaluate ty's IDE completion paths.

Server (LSP) debugging

  • Run ruff server or ty server with verbose logging into a file the editor will display.
  • Most LSP issues reproduce as unit tests in crates/ruff_server/src/server/ or crates/ty_server/src/server/. Add a test before fixing.
  • The LSP wire protocol is JSON-RPC over stdio; you can cat a recorded session into the binary to reproduce client behavior.

When in doubt, capture the input file, the command line, and the Ruff or ty version, and share them in the issue.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Debugging – Ruff wiki | Factory