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.pyCrate-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_cachety 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_benchmarkcrates/ty_completion_bench and crates/ty_completion_eval benchmark and evaluate ty's IDE completion paths.
Server (LSP) debugging
- Run
ruff serverorty serverwith verbose logging into a file the editor will display. - Most LSP issues reproduce as unit tests in
crates/ruff_server/src/server/orcrates/ty_server/src/server/. Add a test before fixing. - The LSP wire protocol is JSON-RPC over stdio; you can
cata 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.