astral-sh/ruff · error · ValueError
Invalid collection element type: {rule}
Error message
Invalid collection element type: {rule} What it means
For sequence fields the generator requires a bare element type name. FieldType.__init__ raises this ValueError when the extracted element is empty ('Vec<>') or contains any of the characters ? * & [ ] < > — which rules out nested generics like 'Vec<Box<Expr>>' or 'Box<[Vec<Stmt>]>', because the codegen cannot synthesize element accessors for such types.
Source
Thrown at crates/ruff_python_ast/generate.py:284
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:
raise ValueError(f"`?` must be at the end: {rule}")
self.optional = True
rule = rule[:-1]
self.sequence_kind, self.name = split_sequence_type(rule)
if self.optional and self.sequence_kind is not None:
raise ValueError(f"optional field cannot be sequence or slice: {self.rule}")
if self.sequence_kind is not None and (
not self.name or any(ch in self.name for ch in "?*&[]<>")
):
raise ValueError(f"Invalid collection element type: {rule}")
self.inner = extract_type_argument(self.name)
# ------------------------------------------------------------------------------
# Preamble
def write_preamble(out: list[str]) -> None:
out.append("""
// This is a generated file. Don't modify it by hand!
// Run `crates/ruff_python_ast/generate.py` to re-generate the file.
use crate::name::Name;
use crate::visitor::source_order::SourceOrderVisitor;
""")
View on GitHub (pinned to d1087a4b9e)
Solutions
- Use a bare type name as the element ('Vec<Expr>'); the generator inserts boxing where the node definition requires it.
- If elements must be shared or complex, introduce a distinct AST node type instead of nesting generics in the rule.
- Re-run the generator and verify the produced Rust field type.
Example fix
# before values: Vec<Box<Expr>> # after (element must be a bare type name) values: Vec<Expr>
Defensive patterns
Strategy: validation
Validate before calling
BAD_CHARS = set('?*&[]<>')
def element_ok(rule: str) -> bool:
for prefix, suffix in (('Vec<', '>'), ('ThinVec<', '>'), ('Box<[', ']>')):
if rule.startswith(prefix) and rule.endswith(suffix):
element = rule[len(prefix):-len(suffix)]
return bool(element) and not BAD_CHARS & set(element)
return True Prevention
- Sequence elements must be bare type names; the generator handles boxing.
- Introduce a dedicated node type instead of nesting generics in a rule.
When it happens
Trigger: Writing a sequence rule whose element is empty or itself generic: 'Vec<>', 'Vec<Box<Expr>>', 'Box<[Vec<Stmt>]>', then running generate.py.
Common situations: Trying to double-box elements by hand; porting hand-written AST structs that used nested collections; assuming the generator needs explicit boxing inside sequences.
Related errors
- Brackets are not balanced for type {rust_type_str}
- `&T*` is unsupported; use `Box<[T]>`: {rule}
- `*` must be at the end: {rule}
- Unclosed collection type: {rule}
- `?` must be at the end: {rule}
AI-assisted analysis of astral-sh/ruff@d1087a4b9e (2026-08-20).
Data as JSON: /api/errors/dc8b2d901764fd83.
Report an issue: GitHub.