remix-run/react-router · error · Error

Route segment "${segment}" for "${routeId}" cannot contain "

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

Thrown by getRouteSegments() (used by flatRoutes) when a raw filename segment contains a character React Router file-system routing doesn't support outside escape sequences: `*`, `:`, or `/`. The error names the segment, the routeId, and the offending character, and links to the upstream proposal (discussion #9822) for tracking. Escape sequences `[...]` are the supported way to include otherwise-special characters.

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 1fd704a7da)

Solutions

  1. Use bracket-escape syntax for parameters: rename `users:$id.tsx` → `users.$id.tsx` (RR param convention) or `users.[].tsx` style per docs.
  2. Replace `*` splats with RR's catch-all convention (`$.tsx`).
  3. Use `.` (or `\` on Windows normalized) to nest instead of `/` in filenames.
  4. If you genuinely need a literal `*`, `:`, or `/` in a segment, wrap it in brackets per the escape rules — but first check discussion #9822 for current support.

Example fix

// before
//   app/routes/users:$id.tsx          → segment contains ':'
//   app/routes/post*.tsx               → segment contains '*'
// after
//   app/routes/users.$id.tsx           → /users/:id
//   app/routes/post.$.tsx              → /post/* (splat)
Defensive patterns

Strategy: validation

Validate before calling

// prebuild filename linter
import { basename } from 'node:path';
import { globSync } from 'node:fs';
for (const file of globSync('app/routes/**')) {
  for (const segment of basename(file).split('.')) {
    if (['*',':','/'].some((c) => segment.includes(c)) && !/^\[.*\]$/.test(segment)) {
      console.warn(`${file}: segment '${segment}' contains an unsupported character`);
    }
  }
}

Type guard

function isSupportedRouteSegment(rawSegment: string): boolean {
  return !['*',':','/'].some((c) => rawSegment.includes(c));
}

Prevention

When it happens

Trigger: A route filename like app/routes/users:$id.tsx, app/routes/post*.tsx, or app/routes/a/b.tsx where the raw segment (before bracket-escaping) contains `*`, `:`, or `/`. The pushRouteSegment helper scans rawSegment for these characters and calls notSupportedInRR.

Common situations: Coming from Next.js / Express conventions and naming files with `:param` or `*` splats. Using `/` inside a filename to denote nesting instead of `.` (the RR convention). Forgetting that `[param]` is the escape mechanism.

Related errors


AI-assisted analysis of remix-run/react-router@1fd704a7da (2026-08-12). Data as JSON: /api/errors/98e197cf340bcbfb. Report an issue: GitHub.