remix: [Bug]: Route filename starting with escaped at-sign [@] does not match

Which Remix packages are impacted?

  • remix (Remix core)
  • @remix-run/react

What version of Remix are you using?

1.0.6

Steps to Reproduce

  1. Create a file [@]hello.jsx in app/routes
  2. Visit https://example.com/@hello

Expected Behavior

The route matches successfully.

Actual Behavior

No routes matched location "/@hello"
GET /@hello 404 - - 17.564 ms

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 1
  • Comments: 18

Most upvoted comments

If for some reason you still want to use something like filename [@]$username.tsx

The reason is that we want the router to perform all routing requirements, and not have to create a wide dynamic segment then manually filter out values that do not begin with the intended prefix manually.

What I mean by this is having to perform something like this in every nested route:

invariant(params.username && params.username[0] === '@' && params.username.length > 1, 'invalid')

When the desired routing is /[@]$username but we are left only with the option to use /$username then any incoming request where the first character is not '@' requires custom 404 handling

The router should be the perfect place for this behaviour to be implemented

I created a patch to backport React Router PR #9300 to React Router 6.3 which is the version pinned in Remix.

This fix allows non-alphanumeric characters to start a route path. This means /@user or /.well-known/ or even /😍 will work.

Currently this only patches the development build as the production files are minified. I will update the patch once I setup to build React Router locally.

https://gist.github.com/kiliman/1a8eb57a6558c96d292bb913add5a178

Any updates on this? This is still broken in v1.12. The workarounds listed by @soungrong are useful but this still needs to be fixed. Having a set of urls start with a prefix followed by a dynamic segment is a pretty common occurrence.

Just to summarize this issue before I close it:

  1. As far as the issue description is concerned, this bug is fixed as of remix v1.10.0 and you can URL match /@hello as long as you’re using a static pattern, e.g. filename [@]hello.tsx.

  2. If you want to URL match /@user or /@user2 or /@user3 dynamically with a single route, then that entire segment must be dynamic, and then handled/routed by yourself. Like this sample https://github.com/remix-run/remix/issues/846#issuecomment-1367587376

This was confirmed by @brophdawg11 in RR 6.5.0 https://github.com/remix-run/react-router/releases/tag/react-router%406.5.0 and PR here https://github.com/remix-run/react-router/pull/9506

  1. If for some reason you still want to use something like filename [@]$username.tsx and pin yourself to remix v1.8.2 then that’s actually possible with the patch here: https://github.com/remix-run/remix/issues/846#issuecomment-1277776319

Not a permanent solution but it seems that with the latest (stable) version it is possible to handle this in $handle.tsx by parsing the params.handle:

export async function loader({ request, params }: LoaderArgs) {
  let handle = params.handle.startsWith("@") ? params.handle.slice(1) : null;

  if (!handle) {
     throw new Response("Not Found", {
      status: 404,
    });
  }

  // ...
}

I had the same problem when using remix 1.7.2 This problem only occurs when trying to match root route.

For example

/xxx/@user can be match with app/routes/xxx/$user.tsx

But /@user can not be match with app/routes/$user.tsx

Yes, the patch does break the test /user2 matches /user. I’m actually trying to come up with the correct solution, but everything I’ve tried so far seems to break other tests.

I’m still learning how the pattern matching process works.