rwf2/Rocket · error · rocket_codegen::param::Error
EarlyTrailing
EarlyTrailing
Error message
unexpected text after trailing parameter
What it means
Compile-time error from Rocket's codegen: a trailing parameter <name..> was declared, but another segment follows it in the same route. In parse_many, once a segment with trailing=true is seen, the iterator latches it and every subsequent (non-empty) segment returns ErrorKind::EarlyTrailing with the trailing segment's span. A trailing parameter by definition consumes the rest of the path/query, so nothing may come after it.
Source
Thrown at core/codegen/src/attribute/param/parse.rs:102
.emit_as_item_tokens();
}
Ok(Parameter::Static(Name::new(segment, source_span)))
}
pub fn parse_many<P: Part>(
source: &str,
source_span: Span,
) -> impl Iterator<Item = Result<Self, Error<'_>>> {
let mut trailing: Option<(&str, Span)> = None;
// We check for empty segments when we parse an `Origin` in `FromMeta`.
source.split(P::DELIMITER)
.filter(|s| !s.is_empty())
.enumerate()
.map(move |(i, segment)| {
if let Some((trail, span)) = trailing {
let error = Error::new(trail, span, ErrorKind::EarlyTrailing)
.source(source, source_span);
return Err(error);
}
let segment_span = subspan(segment, source, source_span);
let mut parsed = Self::parse::<P>(segment, segment_span)
.map_err(|e| e.source(source, source_span))?;
if let Some(ref mut d) = parsed.dynamic_mut() {
if d.trailing {
trailing = Some((segment, segment_span));
}
d.index = i;
}
Ok(parsed)View on GitHub (pinned to 3a54d079ae)
Solutions
- Move the trailing parameter to the very end: #[get("/edit/<path..>")] instead of #[get("/<path..>/edit")]
- Or make the parameter non-trailing (<path>) if it should match a single segment only
- Or split into two routes if the suffix routes need distinct handlers
Example fix
// before
#[get("/<path..>/edit")]
fn edit(path: Path<String>) { }
// after
#[get("/edit/<path..>")]
fn edit(path: Path<String>) { } Defensive patterns
Strategy: validation
Prevention
- Keep <name..> as the last segment of the route, always
- Use <name> (single segment) when a literal suffix must follow
- Split into multiple routes when suffix semantics differ
When it happens
Trigger: #[get("/<path..>/edit")] — segment after a trailing param; #[get("/a/<rest..>/b")]; also in query strings: /search?<params..>&<page>.
Common situations: Adding a suffix route segment (like /edit or a format extension) after an existing catch-all; merging two routes and forgetting to remove a trailing catch-all; assuming <rest..> behaves like a glob that can be followed by literal text.
Related errors
AI-assisted analysis of rwf2/Rocket@3a54d079ae (2026-08-16).
Data as JSON: /api/errors/bc9ae1d01cfb4c6f.
Report an issue: GitHub.