withastro/astro · error · Error

Invalid route — rest parameter must be a standalone segment

Error message

Invalid route ${file} — rest parameter must be a standalone segment

What it means

A rest parameter [...param] matches one or more whole path segments, so it is only meaningful when it occupies an entire segment by itself. validateSegment throws when the segment has content before or after [...param] (regex /.+[[.]{{3}}.../ or /[...].+/) AND the file is an .astro page (the .mdx and API-route variants are handled elsewhere). Mixing text with a rest param would make segment-boundary matching ambiguous.

Solutions

  1. Move the rest parameter into its own directory segment: rename foo[...slug].astro to foo/[...slug].astro (matches /foo/anything/here).
  2. If you need a static prefix plus one dynamic segment, use a normal param instead: foo/[slug].astro.
  3. For nested docs, combine levels: src/pages/docs/[...slug].astro with getStaticPaths generating the paths.

Example fix

// before
src/pages/docs[...slug].astro   // throws: rest parameter must be a standalone segment

// after
src/pages/docs/[...slug].astro   // matches /docs/getting-started/quickstart
Defensive patterns

Strategy: validation

Validate before calling

const REST_PARAM_ATTACHED = /.+(\[\.\.\.[^\]]+\])|(\[\.\.\.[^\]]+\]).+/;

function isStandaloneRestSegment(segment: string): boolean {
  return !REST_PARAM_ATTACHED.test(segment);
}
// reject pages/ filenames like docs[...slug].astro before build

Prevention

When it happens

Trigger: Naming an .astro file where [...slug] is glued to other characters in the same segment: src/pages/foo[...slug].astro, src/pages/[...slug]-bar.astro, src/pages/[lang]/docs[...rest].astro.

Common situations: Trying to build URLs like /docs/a/b/c with a single file instead of a directory; prefixing a catch-all (e.g. [locale][...path]); converting a Next.js catch-all route (**/slug) to Astro one-to-one.

Related errors


AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18). Data as JSON: /api/errors/636d2dd549daf722. Report an issue: GitHub.

Appendix: source

Thrown at packages/astro/src/core/routing/segment.ts:14

export function validateSegment(segment: string, file = '') {
	if (!file) file = segment;

	if (segment.includes('][')) {
		throw new Error(`Invalid route ${file} \u2014 parameters must be separated`);
	}
	if (countOccurrences('[', segment) !== countOccurrences(']', segment)) {
		throw new Error(`Invalid route ${file} \u2014 brackets are unbalanced`);
	}
	if (
		(/.+\[\.\.\.[^\]]+\]/.test(segment) || /\[\.\.\.[^\]]+\].+/.test(segment)) &&
		file.endsWith('.astro')
	) {
		throw new Error(`Invalid route ${file} \u2014 rest parameter must be a standalone segment`);
	}
}

function countOccurrences(needle: string, haystack: string) {
	let count = 0;
	for (const hay of haystack) {
		if (hay === needle) count += 1;
	}
	return count;
}

View on GitHub (pinned to 52e6c34790)