astral-sh/ruff · error
Expected a ty `File`, found a ruff `SourceFile`
Error message
Expected a ty `File`, found a ruff `SourceFile`
What it means
ruff_db's Span unifies the two file kinds — UnifiedFile::Ty(File) for ty and UnifiedFile::Ruff(SourceFile) for ruff lint code — so shared diagnostic machinery can render both. expect_ty_file() unwraps the ty variant and panics when the span actually wraps a ruff SourceFile. Hitting it means a ty-only code path (ty rendering or semantic APIs) received a span produced on ruff's side.
Source
Thrown at crates/ruff_db/src/diagnostic/mod.rs:1277
}
/// Returns a new `Span` with the given `range` attached to it.
pub fn with_range(self, range: TextRange) -> Span {
self.with_optional_range(Some(range))
}
/// Returns a new `Span` with the given optional `range` attached to it.
pub fn with_optional_range(self, range: Option<TextRange>) -> Span {
Span { range, ..self }
}
/// Returns the [`File`] attached to this [`Span`].
///
/// Panics if the file is a [`UnifiedFile::Ruff`] instead of a [`UnifiedFile::Ty`].
pub fn expect_ty_file(&self) -> File {
match self.file {
UnifiedFile::Ty(file) => file,
UnifiedFile::Ruff(_) => panic!("Expected a ty `File`, found a ruff `SourceFile`"),
}
}
/// Returns the [`SourceFile`] attached to this [`Span`].
///
/// Panics if the file is a [`UnifiedFile::Ty`] instead of a [`UnifiedFile::Ruff`].
fn expect_ruff_file(&self) -> &SourceFile {
self.as_ruff_file()
.expect("Expected a ruff `SourceFile`, found a ty `File`")
}
/// Returns the [`SourceFile`] attached to this [`Span`].
pub fn as_ruff_file(&self) -> Option<&SourceFile> {
match &self.file {
UnifiedFile::Ty(_) => None,
UnifiedFile::Ruff(file) => Some(file),
}
}View on GitHub (pinned to d1087a4b9e)
Solutions
- Branch on the variant first: inspect span.file() / as_ruff_file() and only call ty logic for the ty variant, handling the ruff case separately.
- If a function genuinely requires a ty File, change its signature to accept File directly so misuse becomes a compile error instead of a runtime panic.
- When touching shared rendering code, audit call sites of expect_ty_file() in the same change.
Example fix
// before
let file = span.expect_ty_file(); // panics: Expected a ty `File`, found a ruff `SourceFile`
// after
match span.file() {
UnifiedFile::Ty(file) => render_ty(file, span.range()),
UnifiedFile::Ruff(source) => render_ruff(source, span.range()),
} Defensive patterns
Strategy: type-guard
Validate before calling
debug_assert!(
matches!(span.file(), UnifiedFile::Ty(_)),
"ty-only path received a ruff span"
); Type guard
fn is_ty_span(span: &Span) -> bool {
matches!(span.file(), UnifiedFile::Ty(_))
} Prevention
- Never call expect_ty_file() on spans from shared entry points; match on span.file() instead.
- Type module boundaries on File (ty) or SourceFile (ruff) directly so mixing is a compile error.
- Add unit tests that push both file kinds through shared rendering code.
When it happens
Trigger: Calling span.expect_ty_file() (or a helper that does) on a Span built from a ruff SourceFile — typically when shared printer/renderer code in ruff_db is extended and the ruff branch flows into a ty-only function, or ruff lint diagnostics are fed into ty rendering.
Common situations: Refactoring the unified diagnostics layer so a path that previously only saw ty Files now also receives ruff SourceFiles; wiring ruff lint output through the same renderer as ty diagnostics.
Related errors
- should be set because `extract_if` only yields elements with
- `parsed_module` should have assigned a node index
- argument index should not be out of range
- extra use-def data should have been retained
- Expected a Title
AI-assisted analysis of astral-sh/ruff@d1087a4b9e (2026-08-20).
Data as JSON: /api/errors/8fbad7b8d0a6855e.
Report an issue: GitHub.