astral-sh/ruff · info
module to include at least one segment
Error message
module to include at least one segment
What it means
isort's `module_base` returns the first dot-separated segment of a module name (e.g. `foo` from `foo.bar.baz`). The `.expect("module to include at least one segment")` encodes the invariant that `str::split` always yields at least one item — which is true for any &str, since splitting never produces an empty iterator. The panic is therefore unreachable for borrowed module names.
Source
Thrown at crates/ruff_linter/src/rules/isort/types.rs:51
}
#[derive(Debug, Default, Clone)]
pub(crate) struct ImportFromCommentSet<'a> {
pub(crate) atop: Vec<Cow<'a, str>>,
pub(crate) inline: Vec<Cow<'a, str>>,
pub(crate) trailing: Vec<Cow<'a, str>>,
}
pub(crate) trait Importable<'a> {
fn module_name(&self) -> Cow<'a, str>;
fn module_base(&self) -> Cow<'a, str> {
match self.module_name() {
Cow::Borrowed(module_name) => Cow::Borrowed(
module_name
.split('.')
.next()
.expect("module to include at least one segment"),
),
Cow::Owned(module_name) => Cow::Owned(
module_name
.split('.')
.next()
.expect("module to include at least one segment")
.to_owned(),
),
}
}
}
impl<'a> Importable<'a> for AliasData<'a> {
fn module_name(&self) -> Cow<'a, str> {
Cow::Borrowed(self.name)
}
}
View on GitHub (pinned to 26f38c119c)
Solutions
- Leave as-is: split().next() on a &str is infallible; consider documenting the invariant in the comment
- If desired, use `match module_name.split('.').next() { Some(base) => ..., None => unreachable via types }` or model the module name as a non-empty type
- Avoid switching to a filtering split that could legitimately return empty
Example fix
// before
module_name.split('.').next().expect("module to include at least one segment")
// after
// split always yields at least one item; keep expect or switch to a non-empty type
module_name.split('.').next().unwrap_or(module_name) Defensive patterns
Strategy: fallback
Type guard
fn module_base_safe(name: &str) -> &str { name.split('.').next().unwrap_or(name) } Prevention
- Remember str::split never yields an empty iterator — this expect is unreachable
- Document the invariant where the expect lives
- Model non-empty strings in the type system if the invariant matters
When it happens
Trigger: Not triggerable by user input: `"".split('.')` still yields one empty string. It could only fire if the code were changed to a different splitting method (e.g. a filter that drops empty segments) or if module_name could be a non-str type.
Common situations: Contributors hit this only as a false-positive code smell (clippy/analysis tools flagging the expect) or when refactoring module_name to an Option<Vec<Segment>> representation.
Related errors
- Expected `NamedTuple` definition r.h.s. to be a call express
- Expected Stmt::Import | Stmt::ImportFrom
- PySourceType always parses into a module
- Stack to never be empty
- storage-free owned constraint sets must have terminal roots
AI-assisted analysis of astral-sh/ruff@26f38c119c (2026-09-05).
Data as JSON: /api/errors/973fbc4e664594b5.
Report an issue: GitHub.