V5: `OrganizationProfile` throws error upon logout
oferitz opened this issue · 15 comments
Preliminary Checks
- I have reviewed the documentation: https://clerk.com/docs
- I have searched for existing issues: https://github.com/clerk/javascript/issues
- I have not already reached out to Clerk support via email or Discord (if you have, no need to open an issue here)
- This issue is not a question, general help request, or anything other than a bug report directly related to Clerk. Please ask questions in our Discord community: https://clerk.com/discord.
Reproduction
Publishable key
Description
The issue only happens in V5.
Using the OrganizationProfile
in Next.js server component:
/org/[[...org]]/page
export default function OrganizationPage() {
return (
<>
Loading...
)
}
- But when signing out with the
UserButton
<SignedIn>
<UserButton />
</SignedIn>
- You get this screen for a second and redirected to
/sign-in
page as expected
Like I mentioned above, the exact same flow works in V4 without errors, so I guess it's some kind of version regression. I want to upgrade to V5 but can't currently do so due to this issue. Please check, thanks.
Environment
System:
OS: macOS 14.4.1
CPU: (11) arm64 Apple M3 Pro
Memory: 733.31 MB / 36.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 20.11.1 - /usr/local/bin/node
npm: 10.2.4 - /usr/local/bin/npm
pnpm: 9.0.4 - /opt/homebrew/bin/pnpm
Browsers:
Chrome: 123.0.6312.124
Safari: 17.4.1
npmPackages:
@biomejs/biome: 1.7.0 => 1.7.0
@clerk/nextjs: 5.0.1 => 5.0.1
@clerk/themes: 1.7.13 => 1.7.13
@clerk/types: 4.0.0 => 4.0.0
@datadog/browser-rum: 5.14.0 => 5.14.0
@hookform/resolvers: 3.3.4 => 3.3.4
@nextui-org/react: 2.3.4 => 2.3.4
@playwright/test: 1.42.1 => 1.42.1
@splitsoftware/splitio: 10.25.2 => 10.25.2
@splitsoftware/splitio-react: 1.11.1 => 1.11.1
@tanstack/react-query: 5.28.14 => 5.28.14
@tanstack/react-table: 8.16.0 => 8.16.0
@testing-library/react: 15.0.2 => 15.0.2
@types/node: 20 => 20.12.7
@types/react: 18 => 18.2.79
@types/react-dom: 18 => 18.2.25
@vitejs/plugin-react: 4.2.1 => 4.2.1
autoprefixer: 10.4.18 => 10.4.18
axios: 1.6.8 => 1.6.8
clsx: 2.1.0 => 2.1.0
dayjs: 1.11.10 => 1.11.10
fast-deep-equal: 3.1.3 => 3.1.3
framer-motion: 11.0.24 => 11.0.24
jotai: 2.8.0 => 2.8.0
jsdom: 24.0.0 => 24.0.0
lucide-react: 0.364.0 => 0.364.0
next: 14.2.2 => 14.2.2
next-themes: 0.2.1 => 0.2.1
nextjs-toploader: 1.6.11 => 1.6.11
orval: 6.26.0 => 6.26.0
postcss: 8 => 8.4.38
prettier: 3.2.5 => 3.2.5
react: 18 => 18.2.0
react-confetti: 6.1.0 => 6.1.0
react-dom: 18 => 18.2.0
react-hook-form: 7.51.3 => 7.51.3
reactflow: 11.11.0 => 11.11.0
recharts: 2.12.5 => 2.12.5
sonner: 1.4.41 => 1.4.41
tailwind-merge: 2.2.2 => 2.2.2
tailwindcss: 3.4.3 => 3.4.3
typescript: 5 => 5.4.5
vite-tsconfig-paths: 4.3.2 => 4.3.2
vitest: 1.5.0 => 1.5.0
zod: 3.22.4 => 3.22.4
Hi!
Sorry to hear you're running into an issue. To help us best begin debugging the underlying cause, it is incredibly helpful if you're able to create a minimal reproduction. This is a simplified example of the issue that makes it clear and obvious what the issue is and how we can begin to debug it.
If you're up for it, we'd very much appreciate if you could provide a minimal reproduction and we'll be able to take another look.
Thanks for using Clerk!
Hey @oferitz thanks for reporting this. For quickly confirming if the issue has been fixed, you could add do this
<ClerkProvider clerkJSVersion="5.2.0-snapshot.vfc5e305" {...} />
@panteliselef Thanks! It does solve the original issue, but it strangely introduces a new one:
Yeah, this seems to be unrelated, we are already tracking this internally.
Do you mind doing this explicitly ?
<OrganizationProfile
routing="path"
path="/organization"
/>
@panteliselef Sure, do i need to change the folder structure? because doing this with the current catch-all doesn't seem to render anything on the screen.
Is /organization
a nested route ? I couldn't tell from the screenshot above, but yes the file structure should match the path.
OK i made the necessary changes and it renders now, but the error is still present upon signout:
Error: Clerk: The "/main/organization" route is not a catch-all route. It is recommended to convert this route to a catch-all route, eg: "/main/organization/[[...rest]]/page.tsx". Alternatively, update the OrganizationProfile component to use hash-based routing by setting the "routing" prop to "hash".
Thanks for the information, this will help us better understand why this is happening. Seems like you are still blocked which is very unfortunate. We have prioritized this issue and we are expecting a fix soon.
Maybe for you to get unblocked you could simply use routing="hash"
(with no path) for now.
@panteliselef Thanks a lot for the help. Yeah, sure, I can use the hash workaround for now, but please keep me updated once it's fixed
@oferitz this got closed automatically, we are still tracking the 2nd issue you reported, but since the original one is fixed I would keep this closed.
Try updating to latest @clerk/nextjs and removing the clerkJSVersion
prop.
@panteliselef Thanks for the update. Is there a way for me to track the 2nd issue?
Hello @oferitz , I'm currently on the issue and I will try to share more details once my investigation is over.
I do have a few ideas about potential edge cases that are related to the way we detect if a route is a catch-all route or not. Could you please share your middleware code?
I'm very interested to find out how you're protecting your routes as this might be connected and it will certainly help me debug :)
@nikosdouvlis Sure.
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'
const isMainRoute = createRouteMatcher(['/main(.*)'])
export default clerkMiddleware((auth, request) => {
if (isMainRoute(request)) {
auth().protect()
}
})
export const config = {
matcher: ['/((?!.+\\.[\\w]+$|_next).*)', '/', '/(api|trpc)(.*)']
}
@oferitz Thank you very much, this does confirm my initial findings. The problem you're hitting is caused by the auth().protect()
logic in your middleware. Let me give you some context:
All Clerk components can navigate through their own pages using 3 different strategies:
- path routing: the components will modify the path of the URL that comes after the path they are mounted. Example: if you mount your org profile on
/main/organization
, the component will use/main/organization
as its main route but it will use/main/organization/settings
to display the settings page. In this case, we need a catch-all route so the/settings
part can be handled by the Clerk component. This is the default for Clerk components in Nextjs apps. - hash routing: this only modifies just the fragment (the part of the URL that comes after
#
). This does not need a catch-all route because changing the fragment does not need to trigger a NextJS navigation - in memory routing: mainly used by modals, does not affect the URL at all but its not bookmarkable -refreshing the page will cause the component to lose its state
When you mount a path-based Clerk component, we try to check whether you are using a catch-all route or not. The only way to do this in NextJS right now is to fire a request to a random URL under the path the component is mounted (eg /main/organization/clerk_catchall_route_check_123123
) and see whether this returns a 404 or not.
In your case, a race condition after signing out triggers the error as the component incorrectly fires the catch_all_check request I described above, but this fails because auth().protect()
will block the route as you are signed out.
We're sorry for the trouble! This would be very hard to debug on your own. I'm working on updating the detection logic so this false-positive cannot happen again
@nikosdouvlis Thanks for the thorough explanation. I was actually wondering how you do this check, so thanks for sharing this info. I appreciate the effort. Please keep me posted once it's fixed.