astral-sh/ruff · error
Expected ScopeKind::Function | ScopeKind::Lambda
Error message
Expected ScopeKind::Function | ScopeKind::Lambda
What it means
Internal panic in Ruff's flake8-unused-arguments implementation (ARG rules). `unused_arguments` dispatches on `scope.kind` and handles `Function` and `Lambda` scopes, treating any other scope kind as unreachable because the checker only invokes the rule for those two scope types. Hitting it signals a violated internal invariant — a Ruff bug, not a user error.
Source
Thrown at crates/ruff_linter/src/rules/flake8_unused_arguments/rules/unused_arguments.rs:530
&& !visibility::is_abstract(decorator_list, checker.semantic())
&& !visibility::is_override(decorator_list, checker.semantic())
&& !visibility::is_overload(decorator_list, checker.semantic())
{
// we use `method()` here rather than `function()`, as although `__new__` is
// an implicit staticmethod, `__new__` methods must always have at least one parameter
method(Argumentable::StaticMethod, parameters, scope, checker);
}
}
}
}
ScopeKind::Lambda(ast::ExprLambda { parameters, .. }) => {
if let Some(parameters) = parameters {
if checker.is_rule_enabled(Argumentable::Lambda.rule_code()) {
function(Argumentable::Lambda, parameters, scope, checker);
}
}
}
_ => panic!("Expected ScopeKind::Function | ScopeKind::Lambda"),
}
}
View on GitHub (pinned to 26f38c119c)
Solutions
- Pin or upgrade Ruff to a release where the ARG scope dispatch bug is fixed; search the repo issues for 'Expected ScopeKind::Function | ScopeKind::Lambda'
- Reproduce with `ruff check --isolated --select ARG <file>` and minimize the file, then report the snippet upstream
- Exclude ARG rules from the run (`ignore = ["ARG"]` in `lint`) until fixed
- If you call `unused_arguments` from the ruff_linter API, guard your caller to only pass `ScopeKind::Function` or `ScopeKind::Lambda` scopes
Example fix
# before ruff check --select ARG001,ARG002,ARG005 . # after (suppress the crashing rule family until the regression is fixed) [tool.ruff.lint] ignore = ["ARG"]
Defensive patterns
Strategy: validation
Validate before calling
// Rust caller-side guard before invoking the rule
if !matches!(scope.kind, ScopeKind::Function(_) | ScopeKind::Lambda(_)) {
return; // skip instead of reaching the panic arm
} Type guard
fn is_fn_or_lambda_scope(scope: &Scope) -> bool {
matches!(scope.kind, ScopeKind::Function(_) | ScopeKind::Lambda(_))
} Prevention
- Only schedule ARG rules for function/lambda scopes in the checker traversal
- Pin Ruff versions in CI and upgrade after checking the changelog
- Minimize and report any ARG panic to the Ruff issue tracker
- As a codebase user: keep `lint.ignore` ready to drop `ARG` temporarily if a release crashes
When it happens
Trigger: Linting code where the unused-arguments check is entered from a scope whose `kind` is neither a function nor a lambda (e.g. module/class scope). Only reachable through a Ruff regression, a custom plugin registering the visitor on the wrong scope, or desynced scope stack after parser/semantic-model changes.
Common situations: Running `ruff check --select ARG` on a codebase after a Ruff upgrade that changed scope construction; forks or API consumers of the linter crates that call `unused_arguments` directly with an incorrect scope; exotic syntax triggering a scope-classification bug.
Related errors
- Expected Stmt::ImportFrom
- Expected Stmt::Import | Stmt::ImportFrom
- Expected ScopeKind::Function
- Expected CmpOp::Is | CmpOp::IsNot
- extra use-def data should have been retained
AI-assisted analysis of astral-sh/ruff@26f38c119c (2026-09-05).
Data as JSON: /api/errors/58d5a4d535321d69.
Report an issue: GitHub.