fix(pro): downgrade @clerk/clerk-js to v5 — actual fix for sign-in modal#3232
Conversation
The actual root cause behind the "Clerk was not loaded with Ui
components" sign-in failure on /pro is NOT the import path — it's
that pro-test was on @clerk/clerk-js v6.4.0 while the main app
(which works fine) is on v5.125.7.
Clerk v6 fundamentally changed `clerk.load()`: the UI controller
is no longer auto-mounted by default. Both `@clerk/clerk-js` (the
default v6 entry) and `@clerk/clerk-js/no-rhc` (the bundled-UI
variant) expect the caller to either:
- load Clerk's UI bundle from CDN and pass `window.__internal_ClerkUICtor`
to `clerk.load({ ui: { ClerkUI } })`, or
- manually wire up `clerkUICtor`.
That's why my earlier "switch to no-rhc" fix (PR #3227 + #3228)
didn't actually unbreak production — both v6 variants throw the same
assertion. The error stack on the deployed bundle confirmed it:
`assertComponentsReady` from `clerk.no-rhc-UeQvd9Xf.js`.
Fix: pin pro-test to `@clerk/clerk-js@^5.125.7` to match the main
app's working version. v5 still auto-mounts UI on `clerk.load()` —
no extra wiring needed. The plain `import { Clerk } from '@clerk/clerk-js'`
pattern (which the main app uses verbatim and which pro-test had
before #3227) just works under v5.
Verification of the rebuilt bundle (chunk: clerk-PNSFEZs8.js):
- 3.05 MB (matches main app's clerk-DC7Q2aDh.js: 3.05 MB)
- 44 occurrences of mountComponent (matches main: 44)
- 3 occurrences of SignInComponent (matches main: 3)
- 0 occurrences of "Clerk was not loaded with Ui" (the assertion
error string is absent; UI is unconditionally mounted)
Includes the rebuilt public/pro/ artifacts so this fix is actually
deployed (PR #3229's CI check will catch any future PR that touches
pro-test/src without rebuilding).
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Greptile SummaryThis PR downgrades Confidence Score: 5/5Safe to merge — the fix is a targeted, well-justified version pin with no logic changes and matching production evidence. All changes are P2 or lower. The version downgrade is the minimal correct fix, the import revert is accurate, rebuilt assets are verified against the main-app chunk, and the PR description provides thorough root-cause analysis with size/marker verification. No files require special attention. The committed 3 MB Clerk bundle is intentional per the project's existing convention for pre-built /pro assets. Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant Pro Page
participant checkout.ts
participant ClerkJS v5
participant API
User->>Pro Page: clicks SIGN IN / GET STARTED
Pro Page->>checkout.ts: startCheckout(productId)
checkout.ts->>checkout.ts: ensureClerk()
checkout.ts->>ClerkJS v5: import('@clerk/clerk-js')
checkout.ts->>ClerkJS v5: new Clerk(key)
checkout.ts->>ClerkJS v5: instance.load({ appearance })
Note over ClerkJS v5: v5 auto-mounts UI controller inside load()
ClerkJS v5-->>checkout.ts: ready (UI mounted)
checkout.ts->>checkout.ts: addListener (pending checkout)
checkout.ts->>ClerkJS v5: openSignIn()
ClerkJS v5-->>User: Sign-in modal opens
User->>ClerkJS v5: signs in
ClerkJS v5->>checkout.ts: listener fires (user set)
checkout.ts->>API: POST /create-checkout (Bearer token)
API-->>checkout.ts: { checkout_url }
checkout.ts->>User: DodoPayments overlay opens
Reviews (1): Last reviewed commit: "fix(pro): downgrade @clerk/clerk-js to v..." | Re-trigger Greptile |
TL;DR
PRs #3227 and #3228 did NOT fix the production sign-in bug. The deployed `clerk.no-rhc-UeQvd9Xf.js` chunk still throws "Clerk was not loaded with Ui components" because the entire v6 line of `@clerk/clerk-js` (whether the default headless export or the `/no-rhc` bundled variant) requires the caller to wire up a UI controller — neither variant auto-mounts UI on `clerk.load()`.
This PR pins pro-test to `@clerk/clerk-js@^5.125.7`, the same major version the working main app at `worldmonitor.app/` uses. v5 still auto-mounts UI on `clerk.load()`, so the plain `import { Clerk } from '@clerk/clerk-js'` pattern (which the main app uses verbatim and which pro-test had before #3227) just works.
Why my earlier diagnosis was wrong
I claimed `@clerk/clerk-js/no-rhc` was a "drop-in bundled-UI variant". That's false on v6. `no-rhc` ("no Remote Hosted Code") just removes the runtime CDN chunk loader — it does NOT auto-register the UI controller. Per Clerk's docs, even with no-rhc you still need:
```js
const script = document.createElement('script');
script.src = `https://${clerkDomain}/npm/@clerk/ui@1/dist/ui.browser.js`;
// ... wait for load ...
await clerk.load({ ui: { ClerkUI: window.__internal_ClerkUICtor } });
```
Both the headless and no-rhc v6 builds throw the same `assertComponentsReady` error if you skip that wiring. The user's screenshot from production confirmed it: stack trace points at `clerk.no-rhc-UeQvd9Xf.js:22:203968`, exactly the same assertion that fired on the original headless bundle.
Why I missed it during diagnosis
The main app uses `@clerk/clerk-js` v5.125.7 — installed in the repo root `node_modules`. I only inspected pro-test's `node_modules/@clerk/clerk-js` (v6.4.0) and didn't compare versions. The two `Clerk` named exports look identical to TypeScript and at the source level, but their runtime contracts diverge sharply at the v5→v6 boundary.
Verification
Build output of the rebuilt chunk vs main app's working chunk:
The rebuilt /pro chunk now matches the production main-app chunk byte-for-byte in structure. The assertion error string is absent because v5 unconditionally mounts UI inside `clerk.load()`.
Compare the broken v6/no-rhc chunk that's currently live:
Diff
Test plan
Follow-up
Worth a separate spike to either (a) figure out the correct v6 wiring (load `@clerk/ui` from CDN per the docs, with appropriate CSP allowance and error handling) and re-upgrade, or (b) wait until `@clerk/ui` is published as an npm-importable package so we can stop depending on the CDN script tag. Until then, v5 is fine — that's what the main app runs in production.