astral-sh/ruff · error

The meta-type of an instance-like type should always have…

Error message

The meta-type of an instance-like type should always have an MRO

What it means

class_namespace_member looks a name up on the meta-type of a class; the expectation is that the meta-type of an instance-like type always has an MRO, so find_name_in_mro_with_policy must return Some. The expect fires when that MRO walk returns None for the class literal being used as the lookup anchor.

Solutions

  1. Reduce to the class plus attribute access that panics and file a ty issue
  2. Inspect the class's metaclass and base chain (cycles, missing bases in stubs) and fix the source or stub definitions
  3. As a contributor: return an undefined place instead of unwrapping when the MRO walk fails, so lookup degrades gracefully
Defensive patterns

Strategy: fallback

Try / catch

let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| check_file(&db, file)));
match result {
    Ok(diags) => diags,
    Err(payload) => { log::warn!("ty panicked on member lookup in {}: {:?}", file, payload); vec![] }
}

Prevention

When it happens

Trigger: Instance/class member lookup where the metaclass's MRO cannot be produced: circular or malformed class hierarchies, stubs with missing bases, or class tables that are stale after incremental edits.

Common situations: Hand-edited or generated stub files with broken `__bases__` chains; exotic metaclasses; LSP incremental rechecks where class metadata changed mid-session.

Related errors


AI-assisted analysis of astral-sh/ruff@5bb508f594 (2026-08-20). Data as JSON: /api/errors/102f2c12e2822278. Report an issue: GitHub.

Appendix: source

Thrown at crates/ty_python_semantic/src/types.rs:3996

                    _ => Some(
                        class
                            .class_member(db, env, name, policy)
                            .map_type(|member| property_wrapper_descriptor(db, env, name, member)),
                    ),
                }
            }

            Type::GenericAlias(alias) if alias.is_typed_dict(db) => {
                Some(alias.origin(db).typed_dict_member(
                    db,
                    env,
                    Some(alias.specialization(db)),
                    name,
                    policy,
                ))
            }

            Type::GenericAlias(alias) => Some(
                ClassType::from(*alias)
                    .class_member(db, env, name, policy)
                    .map_type(|member| property_wrapper_descriptor(db, env, name, member)),
            ),

            Type::SubclassOf(subclass_of_ty) => {
                subclass_of_ty.find_name_in_mro_with_policy(db, env, name, policy)
            }

            // Note: `super(pivot, owner).__class__` is `builtins.super`, not the owner's class.
            // `BoundSuper` should look up the name in the MRO of `builtins.super`.
            Type::BoundSuper(_) => KnownClass::Super
                .to_class_literal(db, env)
                .find_name_in_mro_with_policy(db, env, name, policy),

            // We eagerly normalize type[object], i.e. Type::SubclassOf(object) to `type`,
            // i.e. Type::NominalInstance(type). So looking up a name in the MRO of
            // `Type::NominalInstance(type)` is equivalent to looking up the name in the

View on GitHub (pinned to 5bb508f594)