remix-run/react-router · error
Route segment " " for " " cannot contain " ". If this is…
Error message
Route segment "${segment}" for "${routeId}" cannot contain "${char}".
If this is something you need, upvote this proposal for React Router https://github.com/remix-run/react-router/discussions/9822. What it means
getRouteSegments() parses each file-based route id into URL segments and rejects raw segments containing '*' or ':' — literal splat/param characters that React Router does not currently support in segment names. The message points to the GitHub discussion (#9822) proposing support, telling you to rename the file instead. It is a hard parse-time error raised while flatRoutes() builds the manifest.
Solutions
- Rename the file to remove the '*' or ':' characters
- Use the supported '$param' convention for dynamic segments instead of ':param'
- If you genuinely need the feature, upvote discussion #9822 and restructure routes meanwhile
Example fix
# before app/routes/docs.v*:slug.tsx # after app/routes/docs.$version.$slug.tsx
Defensive patterns
Strategy: validation
Validate before calling
// reject offending filenames before the route manifest is built
import path from "node:path";
for (const file of routeFiles) {
for (const seg of path.basename(file).split(".")) {
if (seg.includes(":") || seg.includes("*")) {
throw new Error(`Rename ${file}: segment '${seg}' contains ':' or '*'`);
}
}
} Prevention
- Use the $param convention for dynamic segments — never :param or *splat in filenames
- Add a filename lint step for the routes directory
- Watch discussion #9822 if you need literal : or * segments
When it happens
Trigger: A route filename whose segment portion contains a literal '*' or ':', e.g. app/routes/docs.v*:slug.tsx or app/routes/schedule.HH:mm.tsx — pushRouteSegment detects the character in the raw segment and throws.
Common situations: Trying to hand-write ':param' or '*splat' URL syntax into flat-routes filenames; migrating from another router's file conventions where those characters are meaningful; naming files after time/colon patterns.
Related errors
- Could not find a root route module in the app directory
- Could not find the routes directory
- Invalid route module exports. The following pairs of…
- Module cannot have both a default export and a…
- Module cannot have both a HydrateFallback export and a…
AI-assisted analysis of remix-run/react-router@6beaca3952 (2026-08-18).
Data as JSON: /api/errors/98e197cf340bcbfb.
Report an issue: GitHub.
Appendix: source
Thrown at packages/react-router-fs-routes/flatRoutes.ts:363
| "ESCAPE"
// we hit a `(` and are now in an optional segment until we hit a `)` or an escape sequence
| "OPTIONAL"
// we previously were in a opt fional segment and hit a `[` and are now in an escape sequence until we hit a `]` - take characters literally and skip isSegmentSeparator checks - afterwards go back to OPTIONAL state
| "OPTIONAL_ESCAPE";
export function getRouteSegments(routeId: string): [string[], string[]] {
let routeSegments: string[] = [];
let rawRouteSegments: string[] = [];
let index = 0;
let routeSegment = "";
let rawRouteSegment = "";
let state: State = "NORMAL";
let pushRouteSegment = (segment: string, rawSegment: string) => {
if (!segment) return;
let notSupportedInRR = (segment: string, char: string) => {
throw new Error(
`Route segment "${segment}" for "${routeId}" cannot contain "${char}".\n` +
`If this is something you need, upvote this proposal for React Router https://github.com/remix-run/react-router/discussions/9822.`,
);
};
if (rawSegment.includes("*")) {
return notSupportedInRR(rawSegment, "*");
}
if (rawSegment.includes(":")) {
return notSupportedInRR(rawSegment, ":");
}
if (rawSegment.includes("/")) {
return notSupportedInRR(segment, "/");
}
routeSegments.push(segment);View on GitHub (pinned to 6beaca3952)