{"record":{"id":"c55cc2648111f503","repo":"astral-sh/ruff","slug":"expected-type-alias","errorCode":null,"errorMessage":"expected type alias","messagePattern":"expected type alias","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ty_python_core/src/scope.rs","lineNumber":446,"sourceCode":"        match self {\n            Self::Function(function) => Some(function),\n            _ => None,\n        }\n    }\n\n    pub fn expect_function(&self) -> &AstNodeRef<ast::StmtFunctionDef> {\n        self.as_function().expect(\"expected function\")\n    }\n\n    fn as_type_alias(&self) -> Option<&AstNodeRef<ast::StmtTypeAlias>> {\n        match self {\n            Self::TypeAlias(type_alias) => Some(type_alias),\n            _ => None,\n        }\n    }\n\n    pub fn expect_type_alias(&self) -> &AstNodeRef<ast::StmtTypeAlias> {\n        self.as_type_alias().expect(\"expected type alias\")\n    }\n\n    /// Returns the anchor node index for this scope, or `None` for the module scope.\n    ///\n    /// This is used to compute relative node indices for expressions within the scope,\n    /// providing a stable anchor that only changes when the scope-introducing node changes.\n    pub fn node_index(&self) -> Option<NodeIndex> {\n        match self {\n            Self::Module => None,\n            Self::Class(class) => Some(class.index()),\n            Self::ClassTypeParameters(class) => Some(class.index()),\n            Self::Function(function) => Some(function.index()),\n            Self::FunctionTypeParameters(function) => Some(function.index()),\n            Self::TypeAlias(type_alias) => Some(type_alias.index()),\n            Self::TypeAliasTypeParameters(type_alias) => Some(type_alias.index()),\n            Self::Lambda(lambda) => Some(lambda.index()),\n            Self::ListComprehension(comp) => Some(comp.index()),\n            Self::SetComprehension(comp) => Some(comp.index()),","sourceCodeStart":428,"sourceCodeEnd":464,"githubUrl":"https://github.com/astral-sh/ruff/blob/d1087a4b9e03d253a88703f34e0869ee4b805456/crates/ty_python_core/src/scope.rs#L428-L464","documentation":"Scope::expect_type_alias unwraps as_type_alias(): it returns the StmtTypeAlias node only when the scope is a TypeAlias scope; any other scope kind panics with 'expected type alias'. It exists so callers like type_alias.rs can unwrap after establishing the scope kind.","triggerScenarios":"Calling expect_type_alias on a scope that is not a TypeAlias scope - misuse of the API, or a code path that reaches a type-alias scope assumption for a scope created by another statement.","commonSituations":"Contributors adding type-alias-related semantic queries; refactors that change scope creation for `type X = ...` statements.","solutions":["Use as_type_alias() and handle None instead of unwrapping","Confirm the scope kind (match ScopeKind) before calling expect_type_alias","If it fires inside ty on valid Python, capture a repro and file an issue"],"exampleFix":"// before\nlet alias_node = scope.node(db).expect_type_alias(); // panics if wrong kind\n\n// after\nlet Some(alias_node) = scope.node(db).as_type_alias() else { return None; };","handlingStrategy":"type-guard","validationCode":"if scope.kind() != ScopeKind::TypeAlias { return None; } // establish kind before unwrapping","typeGuard":"let is_type_alias_scope = |scope: &Scope| matches!(scope.kind(), ScopeKind::TypeAlias);","tryCatchPattern":"match scope.node().as_type_alias() { Some(alias) => { /* ... */ }, None => { /* wrong scope kind: skip or report */ } }","preventionTips":["Use as_type_alias() for any new call site","Confirm the scope was created by a `type X = ...` statement before unwrapping","File an issue with a reproducer if expect_type_alias panics on valid Python"],"tags":["internal","scope","ast","panic","invariant","type-alias"],"backgroundTag":"internal-invariant-violation","analyzedSha":"d1087a4b9e03d253a88703f34e0869ee4b805456","analyzedAt":"2026-08-20T16:33:49.445Z","contentChangedAt":"2026-08-20T16:33:49.445Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}