nushell/nushell · error
Attribute block must contain at least one attribute
Error message
Attribute block must contain at least one attribute
What it means
parse_attribute_block handles a run of '@attr' lines that is not followed by a definition; it exists mainly to emit ParseError::AttributeRequiresDefinition. Before building that error it asserts attributes.last() is Some, i.e. the LiteCommand carried at least one attribute command. It panics only when invoked on a LiteCommand whose attribute_commands() iterator is empty, breaking the contract that only attribute-carrying commands reach this function.
Source
Thrown at crates/nu-parser/src/parse_def.rs:291
},
);
}
Expression::new(working_set, Expr::Call(call), call_span, Type::Nothing)
}
pub fn parse_attribute_block(
working_set: &mut StateWorkingSet,
lite_command: &LiteCommand,
) -> Pipeline {
let attributes = lite_command
.attribute_commands()
.map(|cmd| parse_attribute(working_set, &cmd).0)
.collect::<Vec<_>>();
let last_attr_span = attributes
.last()
.expect("Attribute block must contain at least one attribute")
.expr
.span;
working_set.error(ParseError::AttributeRequiresDefinition(last_attr_span));
let cmd_span = if lite_command.command_parts().is_empty() {
last_attr_span.past()
} else {
Span::concat(lite_command.command_parts())
};
let cmd_expr = garbage(working_set, cmd_span);
let ty = cmd_expr.ty.clone();
let attr_block_span = Span::merge_many(
attributes
.first()
.map(|x| x.expr.span)
.into_iter()
.chain(Some(cmd_span)),View on GitHub (pinned to 8e03210652)
Solutions
- Only call parse_attribute_block when lite_command.attribute_commands().next().is_some()
- Use the normal public parse entry points so the lite parser decides routing
- Sync forked parser code with the nu-parser version you depend on
- Report upstream if plain source input (an '@attr' line followed by nothing) triggers it via the standard path
Example fix
// before: assumes the command has attributes
let pipeline = parse_attribute_block(working_set, &lite_command);
// after: only enter the attribute-block path when attributes exist
if lite_command.attribute_commands().next().is_some() {
let pipeline = parse_attribute_block(working_set, &lite_command);
} else {
// fall through to regular command parsing
} Defensive patterns
Strategy: validation
Validate before calling
if lite_command.attribute_commands().next().is_some() {
let pipeline = parse_attribute_block(working_set, &lite_command);
} else {
// regular command path — parse_attribute_block would panic
} Type guard
fn has_attributes(cmd: &LiteCommand) -> bool {
cmd.attribute_commands().next().is_some()
} Prevention
- Only enter attribute-block handling through the lite parser's own routing
- In tests, build LiteCommands via lite-parsing real source text instead of struct literals
- Keep any forked lite-parser classification logic in lockstep with parse_def.rs expectations
When it happens
Trigger: Calling parse_attribute_block with a LiteCommand that has no attribute commands; a lite-parser regression that routes a plain command into the attribute-block path; hand-constructed LiteCommand values with an empty attribute list.
Common situations: Forked or patched lite parsers; embedders wiring parse stages manually; tests that fabricate LiteCommand structs instead of parsing source text.
Related errors
- Attributes always start with an `@`
- for call already checked
- best_guess should not be None here!
- invalid utf-8 in flag name
- invalid utf-8 in flag short name
AI-assisted analysis of nushell/nushell@8e03210652 (2026-08-17).
Data as JSON: /api/errors/0bac7b80c5c249e6.
Report an issue: GitHub.