astral-sh/ruff · error · ValueError
Unclosed collection type: {rule}
Error message
Unclosed collection type: {rule} What it means
When an AST field rule starts with a known collection prefix (Vec<, ThinVec<, Box<[), split_sequence_type() requires the matching suffix ('>' for Vec/ThinVec, ']>' for Box<[). A rule like 'Vec<Stmt' or 'Box<[Token>' fails this check and raises ValueError.
Source
Thrown at crates/ruff_python_ast/generate.py:255
def split_sequence_type(rule: str) -> tuple[SequenceKind | None, str]:
if "&" in rule:
raise ValueError(f"`&T*` is unsupported; use `Box<[T]>`: {rule}")
if "*" in rule:
if rule.endswith("*") and rule.count("*") == 1:
return SequenceKind.VEC, rule[:-1]
raise ValueError(f"`*` must be at the end: {rule}")
for prefix, suffix, sequence_kind in (
("Vec<", ">", SequenceKind.VEC),
("ThinVec<", ">", SequenceKind.THIN_VEC),
("Box<[", "]>", SequenceKind.BOXED_SLICE),
):
if rule.startswith(prefix):
if not rule.endswith(suffix):
raise ValueError(f"Unclosed collection type: {rule}")
return sequence_kind, rule[len(prefix) : -len(suffix)]
return None, rule
@dataclass
class FieldType:
rule: str
name: str
inner: str
sequence_kind: SequenceKind | None = None
optional: bool = False
def __init__(self, rule: str) -> None:
self.rule = rule
self.optional = False
if "?" in rule:
if not rule.endswith("?") or rule.count("?") != 1:View on GitHub (pinned to d1087a4b9e)
Solutions
- Close Vec<...> and ThinVec<...> with '>', and Box<[...> with ']>'.
- Re-run the generator and check the produced Rust type matches your intent.
- Run cargo check -p ruff_python_ast after regeneration.
Example fix
# before body: Box<[Stmt> # after body: Box<[Stmt]>
Defensive patterns
Strategy: validation
Validate before calling
COLLECTIONS = (('Vec<', '>'), ('ThinVec<', '>'), ('Box<[', ']>'))
def rule_ok(rule: str) -> bool:
return all(
not rule.startswith(p) or rule.endswith(s)
for p, s in COLLECTIONS
) Prevention
- Box<[T]> closes with ']>', not '>'.
- Regenerate immediately after editing collection rules to catch typos early.
When it happens
Trigger: Writing a collection rule whose closing suffix is missing or wrong (e.g. closing a Box<[...> slice with '>' instead of ']>', or omitting the '>'), then running generate.py.
Common situations: Hand-writing Box<[T]> rules for the first time; converting a Vec<T> rule to a boxed slice and forgetting to change the suffix.
Related errors
- `*` must be at the end: {rule}
- Brackets are not balanced for type {rust_type_str}
- `&T*` is unsupported; use `Box<[T]>`: {rule}
- `?` must be at the end: {rule}
- optional field cannot be sequence or slice: {self.rule}
AI-assisted analysis of astral-sh/ruff@d1087a4b9e (2026-08-20).
Data as JSON: /api/errors/5964b76f9355b2fc.
Report an issue: GitHub.