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

  1. Move the trailing parameter to the very end: #[get("/edit/<path..>")] instead of #[get("/<path..>/edit")]
  2. Or make the parameter non-trailing (<path>) if it should match a single segment only
  3. 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

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.