withastro/astro · error · Error
Invalid route — parameter name must match /^[a-zA-Z0-9_$]+$/
Error message
Invalid route ${file} — parameter name must match /^[a-zA-Z0-9_$]+$/ What it means
The routing layer keeps a standalone copy of the segment parser (`getParts` in `core/routing/parts.ts`, used by `parse-route.ts` and other routing utilities, parallel to the one in `create-manifest.ts`). It splits each segment on `[...]` groups and requires dynamic content to match `/^(?:\.\.\.)?[\w$]+$/` — an optional `...` spread prefix, then only `[A-Za-z0-9_$]`. Hyphens, dots, spaces, or unicode inside brackets make the param unusable as an identifier, so parsing throws this plain Error naming the file.
Solutions
- Rename the param to only letters/digits/`_`/`$` (e.g. `[mySlug].astro`) — hyphens remain fine in the URL value, not the param name
- Update `getStaticPaths()` params and `Astro.params` reads to the new name
- Lint `src/pages` for bracket contents failing `/^(?:\.\.\.)?[\w$]+$/` so invalid names fail loudly in CI
Example fix
# before
src/pages/blog/[my-slug].astro
# after
src/pages/blog/[mySlug].astro
# and update: getStaticPaths() → [{ params: { mySlug: 'some-value' } }] Defensive patterns
Strategy: type-guard
Validate before calling
# CI scan over pages (and any externally sourced route names)
for f in $(find src/pages -name '*\[*\]*'); do
grep -oE '\[[^]/]+\]' <<< "$f" | tr -d '[]' | while read -r p; do
p="${p#...}"
isValidRouteParamName "$p" || { echo "invalid param '$p' in $f"; exit 1; }
done
done Type guard
// Same rule Astro enforces when parsing segments
export function isValidRouteParamName(name: string): boolean {
return /^(?:\.\.\.)?[\w$]+$/.test(name);
} Prevention
- Restrict bracket param names to `[A-Za-z0-9_$]` (plus `...` spread prefix)
- Validate route filenames from generators/CMS sources before writing them into src/pages
- Run the filename lint in CI to catch renames and scaffolder output
When it happens
Trigger: Routes like `src/pages/[my-slug].astro`, `src/pages/[slug.json].ts`, `src/pages/[...path-segment].astro`, or unicode names like `[categoría]`; tooling that calls the route-parsing API (parse-route/getParts) directly on generated or user-supplied filenames; renaming directories into bracket notation with invalid characters.
Common situations: Kebab-case param names chosen to mirror URL style; scaffolders injecting arbitrary strings into filenames; sharing route-parsing helpers with external route sources (e.g. CMS-defined routes).
Related errors
- Invalid route — parameter name must match /^[a-zA-Z0-9_$]+$/
- A collision will result in a hard error in following…
- context.params don't contain any usable content in Astro.
- context.rewrite is not available in Astro.
- Couldn't find component for route
AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18).
Data as JSON: /api/errors/485899d98354ffd2.
Report an issue: GitHub.
Appendix: source
Thrown at packages/astro/src/core/routing/parts.ts:17
import type { RoutePart } from '../../types/public/index.js';
// Disable eslint as we're not sure how to improve this regex yet
// eslint-disable-next-line regexp/no-super-linear-backtracking
const ROUTE_DYNAMIC_SPLIT = /\[(.+?\(.+?\)|.+?)\]/;
const ROUTE_SPREAD = /^\.{3}.+$/;
export function getParts(part: string, file: string) {
const result: RoutePart[] = [];
part.split(ROUTE_DYNAMIC_SPLIT).map((str, i) => {
if (!str) return;
const dynamic = i % 2 === 1;
const [, content] = dynamic ? /([^(]+)$/.exec(str) || [null, null] : [null, str];
if (!content || (dynamic && !/^(?:\.\.\.)?[\w$]+$/.test(content))) {
throw new Error(`Invalid route ${file} — parameter name must match /^[a-zA-Z0-9_$]+$/`);
}
result.push({
content,
dynamic,
spread: dynamic && ROUTE_SPREAD.test(content),
});
});
return result;
}
View on GitHub (pinned to 52e6c34790)