astral-sh/ruff · error
there must be a first type if there are conflicting types
Error message
there must be a first type if there are conflicting types
What it means
DeclaredTypeAndConflictingTypesBuilder assembles a symbol's declared type plus the list of conflicting declared types recorded across multiple declarations. Its invariant is that whenever a conflicting type is recorded, the original first declared type is stashed in first_type; build() panics if conflicting_types is non-empty while first_type was never set.
Solutions
- Minimize the module to the two conflicting annotations that trigger the panic and file a ty issue with it
- As a contributor: ensure every path that pushes onto conflicting_types sets first_type beforehand (record the original type before treating later types as conflicts)
- Workaround until fixed: unify or remove one of the conflicting declarations for that name
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 while declaring {}: {:?}", file, payload); vec![] }
} Prevention
- Avoid mixing multiple different annotations for one name across branches in a single module while a triggering bug is unfixed
- When touching conflict collection in place.rs, set first_type on every path that appends to conflicting_types
- Add builder unit tests covering the one-conflict and many-conflicts sequences
When it happens
Trigger: A symbol that receives two or more different declared types (for example `x: int` in one branch and `x: str]` in another, or repeated annotations) where the code path that pushed the conflicting type never recorded the first type first - a builder misuse or a missed update when a new conflict-recording path was added.
Common situations: Modules with multiple differently-annotated declarations of the same name (conditional imports, branch-local annotations); contributor changes to place_from_declarations conflict collection.
Related errors
- accumulator should not be empty
- anchor should not be NodeIndex::NONE
- argument index should be valid
- argument index should be valid
- argument index should not be out of range
AI-assisted analysis of astral-sh/ruff@5bb508f594 (2026-08-20).
Data as JSON: /api/errors/85469f50f6419ad7.
Report an issue: GitHub.
Appendix: source
Thrown at crates/ty_python_semantic/src/place.rs:2145
false
} else {
// An unconditional implementation shadows preceding overload definitions. A
// conditional definition, however, can be only one public possibility among
// several, so keep any unrelated queued overloaded function in the union.
if reachability.is_always_true()
|| self.queue.is_some_and(|queued| {
let Type::FunctionLiteral(queued_function) = queued else {
return false;
};
let queued_definition = queued_function.last_definition(db);
function.contains_definition(db, queued_definition)
})
{
self.queue = None;
} else {
self.drain_queue();
}
self.add_to_union(element);
true
}
}
_ => {
self.drain_queue();
self.add_to_union(element);
true
}
}
}
fn build(mut self) -> Type<'db> {
self.drain_queue();
self.builder.build()
}
}
/// Accumulates multiple (potentially conflicting) declared types and type qualifiers,View on GitHub (pinned to 5bb508f594)