astral-sh/ruff · error
`object` should always be a non-generic class in typeshed
Error message
`object` should always be a non-generic class in typeshed
What it means
`ClassLiteral::object` resolves `builtins.object` from the active `ProgramEnvironment` and asserts it is a plain, non-generic class literal, as typeshed guarantees. The expect fires when the loaded typeshed does not define `object` as a resolvable non-generic class. This is an environment problem (missing/broken/foreign stubs), not something user Python code can cause.
Source
Thrown at crates/ty_python_semantic/src/types/class.rs:631
)]
pub enum ClassLiteral<'db> {
/// A class defined via a `class` statement.
Static(StaticClassLiteral<'db>),
/// A class created dynamically via `type(name, bases, dict)`.
Dynamic(DynamicClassLiteral<'db>),
/// A class created via `collections.namedtuple()` or `typing.NamedTuple()`.
DynamicNamedTuple(DynamicNamedTupleLiteral<'db>),
/// A class created via functional `TypedDict("Name", {...})`.
DynamicTypedDict(DynamicTypedDictLiteral<'db>),
/// A class created via functional enum syntax, e.g., `Enum("Color", "RED GREEN BLUE")`.
DynamicEnum(DynamicEnumLiteral<'db>),
}
#[salsa::tracked]
impl<'db> ClassLiteral<'db> {
/// Return a `ClassLiteral` representing the class `builtins.object`
pub(super) fn object(db: &'db dyn Db, env: &ProgramEnvironment<'db>) -> Self {
KnownClass::Object
.to_class_literal(db, env)
.as_class_literal()
.expect("`object` should always be a non-generic class in typeshed")
}
pub(super) fn recursive_type_normalized_impl(
self,
db: &'db dyn Db,
env: &ProgramEnvironment<'db>,
div: Type<'db>,
nested: bool,
) -> Option<Self> {
match self {
Self::Dynamic(dynamic) => Some(Self::Dynamic(
dynamic.recursive_type_normalized_impl(db, env, div, nested)?,
)),
Self::DynamicNamedTuple(named_tuple) => Some(Self::DynamicNamedTuple(
named_tuple.recursive_type_normalized_impl(db, env, div, nested)?,View on GitHub (pinned to 15f3fe6b15)
Solutions
- Run ty with its bundled default typeshed (remove any custom typeshed/search-path override) and re-check.
- Inspect the typeshed ty loads: `stdlib/builtins.pyi` must contain `class object:` with no type parameters.
- Upgrade/downgrade ty so the binary and its vendored typeshed come from the same release.
- If a custom typeshed is required, restore a standard typeshed checkout (same version the vendored snapshot is pinned to).
Example fix
# before: custom typeshed where stdlib/builtins.pyi is missing or has # class object[T]: ... # after: stdlib/builtins.pyi must declare the plain class # class object: # __module__: str # ...
Defensive patterns
Strategy: validation
Validate before calling
# before pointing ty at a custom typeshed, verify the stub it will load: grep -n '^class object' <typeshed>/stdlib/builtins.pyi # empty output, or a generic `class object[T]`, means this panic is guaranteed
Prevention
- Prefer ty's bundled typeshed; only override it with a full standard checkout.
- Never mix a typeshed snapshot from one ty release with a binary from another.
- Verify custom stub sets contain stdlib/builtins.pyi with a plain `class object:` before wiring them in.
When it happens
Trigger: Running checks with a custom, minimal, outdated, or corrupted typeshed whose `stdlib/builtins.pyi` is missing or does not declare a plain `class object:`; mixing a typeshed snapshot from one ty version with the binary of another; a failed/partial extraction of the vendored typeshed.
Common situations: Pointing ty at a custom stub directory; offline/containers builds that strip the bundled typeshed; upgrading ty in place while an old vendored snapshot remains on disk.
Related errors
- Will return Some() when called on class literal
- Expected `NamedTuple` definition to be an assignment
- Expected `NamedTuple` definition r.h.s. to be a call express
- typevar should be interned before ordering
- storage-free owned constraint sets must have terminal roots
AI-assisted analysis of astral-sh/ruff@15f3fe6b15 (2026-08-20).
Data as JSON: /api/errors/84d879b2c3949f7b.
Report an issue: GitHub.