feat(fastify): actionable error when registered on unsupported Fastify version#8843
feat(fastify): actionable error when registered on unsupported Fastify version#8843h2m6jcm94s-eng wants to merge 1 commit into
Conversation
…y version When @clerk/fastify is registered on Fastify < 5, fastify-plugin's stock `FST_ERR_PLUGIN_VERSION_MISMATCH` tells the user about the mismatch but not how to resolve it. This makes the failure mode harder to act on than it needs to be, especially because Fastify 4 is still LTS and many apps have not migrated yet. This change throws a Clerk-branded error at plugin registration time that explicitly tells the user to either upgrade to fastify@^5 or pin @clerk/fastify@^1 (which still supports Fastify 4 LTS). The `fastify: '5.x'` field is removed from the fastify-plugin metadata so our actionable error wins over fastify-plugin's stock one. The check itself is a one-line integer comparison so no new dependencies are introduced. The README's Prerequisites section is updated to mention the @clerk/fastify@^1 pin path for Fastify 4 LTS users. Tests cover the throw on multiple sub-5 versions (4.28.0, 3.29.5, 2.0.0) and confirm there is no throw on supported versions (5.0.0, 5.8.5, 6.0.0-alpha.1). Signed-off-by: Devayan Dewri <287486912+h2m6jcm94s-eng@users.noreply.github.com>
🦋 Changeset detectedLatest commit: 98734c9 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
@h2m6jcm94s-eng is attempting to deploy a commit to the Clerk Production Team on Vercel. A member of the Team first needs to authorize it. |
📝 WalkthroughWalkthroughThis PR strengthens the Fastify plugin's version compatibility by moving from a static build-time constraint to runtime validation with actionable error guidance. The plugin now detects unsupported Fastify versions and returns a user-friendly message directing them to either upgrade Fastify to v5 or pin the package to v1 for Fastify 4 support. ChangesFastify Version Validation
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
packages/fastify/src/clerkPlugin.ts (1)
13-16: 💤 Low valueConsider adding explicit return type for clarity.
While
parseFastifyMajoris an internal helper, adding an explicit return type (: number) would improve readability and align with TypeScript best practices.📝 Suggested enhancement
-const parseFastifyMajor = (version: string): number => { +const parseFastifyMajor = (version: string): number => { const match = /^(\d+)/.exec(version); return match ? Number.parseInt(match[1]!, 10) : 0; };🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/fastify/src/clerkPlugin.ts` around lines 13 - 16, The helper function parseFastifyMajor should have an explicit return type to improve readability and TypeScript best practices; update the function signature for parseFastifyMajor to declare its return type as number (e.g., ensure the arrow function signature includes ": number") and keep the implementation converting the matched group to a Number via Number.parseInt(match[1], 10) or returning 0 when no match.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/fastify/src/errors.ts`:
- Around line 20-29: The exported function incompatibleFastifyVersion currently
has no explicit return type; update its signature to include the correct return
type (the type returned by createErrorMessage, e.g., string or ErrorMessageType
used across the module) so the public API has an explicit annotation; locate the
incompatibleFastifyVersion declaration and add the appropriate return type
annotation matching createErrorMessage's return (or the module's convention) and
ensure export remains unchanged.
---
Nitpick comments:
In `@packages/fastify/src/clerkPlugin.ts`:
- Around line 13-16: The helper function parseFastifyMajor should have an
explicit return type to improve readability and TypeScript best practices;
update the function signature for parseFastifyMajor to declare its return type
as number (e.g., ensure the arrow function signature includes ": number") and
keep the implementation converting the matched group to a Number via
Number.parseInt(match[1], 10) or returning 0 when no match.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Repository UI (inherited)
Review profile: CHILL
Plan: Pro
Run ID: 5d1636ca-d12f-4a7f-a461-1b737bf85531
📒 Files selected for processing (6)
.changeset/fastify-actionable-version-error.mdpackages/fastify/README.mdpackages/fastify/src/__tests__/clerkPlugin.test.tspackages/fastify/src/clerkPlugin.tspackages/fastify/src/errors.tspackages/fastify/src/test/utils.ts
| export const incompatibleFastifyVersion = (foundVersion: string) => | ||
| createErrorMessage(`@clerk/fastify requires fastify@>=5 but is being registered on fastify@${foundVersion}. | ||
|
|
||
| To resolve this, either: | ||
| - upgrade your fastify dependency to ^5, or | ||
| - pin @clerk/fastify@^1 to keep using fastify@4 (LTS): | ||
|
|
||
| npm install @clerk/fastify@^1 | ||
| # or: pnpm add @clerk/fastify@^1 | ||
| `); |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win
Add explicit return type annotation for the exported function.
The exported function incompatibleFastifyVersion lacks an explicit return type. As per coding guidelines, all exported functions (especially public APIs) should define explicit return types for better type safety and API clarity.
📝 Proposed fix
-export const incompatibleFastifyVersion = (foundVersion: string) =>
+export const incompatibleFastifyVersion = (foundVersion: string): string =>
createErrorMessage(`@clerk/fastify requires fastify@>=5 but is being registered on fastify@${foundVersion}.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export const incompatibleFastifyVersion = (foundVersion: string) => | |
| createErrorMessage(`@clerk/fastify requires fastify@>=5 but is being registered on fastify@${foundVersion}. | |
| To resolve this, either: | |
| - upgrade your fastify dependency to ^5, or | |
| - pin @clerk/fastify@^1 to keep using fastify@4 (LTS): | |
| npm install @clerk/fastify@^1 | |
| # or: pnpm add @clerk/fastify@^1 | |
| `); | |
| export const incompatibleFastifyVersion = (foundVersion: string): string => | |
| createErrorMessage(`@clerk/fastify requires fastify@>=5 but is being registered on fastify@${foundVersion}. | |
| To resolve this, either: | |
| - upgrade your fastify dependency to ^5, or | |
| - pin `@clerk/fastify`@^1 to keep using fastify@4 (LTS): | |
| npm install `@clerk/fastify`@^1 | |
| # or: pnpm add `@clerk/fastify`@^1 | |
| `); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/fastify/src/errors.ts` around lines 20 - 29, The exported function
incompatibleFastifyVersion currently has no explicit return type; update its
signature to include the correct return type (the type returned by
createErrorMessage, e.g., string or ErrorMessageType used across the module) so
the public API has an explicit annotation; locate the incompatibleFastifyVersion
declaration and add the appropriate return type annotation matching
createErrorMessage's return (or the module's convention) and ensure export
remains unchanged.
Source: Coding guidelines
Closes #8844.
Description
When
@clerk/fastifyis registered against Fastify < 5, the failure mode today isfastify-plugin's stockFST_ERR_PLUGIN_VERSION_MISMATCH. That error correctly identifies the mismatch but doesn't tell users what to do about it — and because Fastify 4 is still in LTS, this is a real footgun for teams that haven't migrated yet (and whosepnpm installwarning got buried among other peer-dep noise). See #8844 for the full repro and motivation.This PR replaces the stock error with a Clerk-branded one that spells out both resolution paths:
I hit this firsthand while bootstrapping a Fastify 4 LTS app — the peer-dep warning at install time was easy to miss, and registration failed with the stock error which left me unsure whether to upgrade Fastify or downgrade
@clerk/fastify.Implementation
packages/fastify/src/clerkPlugin.ts— adds a major-version guard at the top of the plugin callback. The check is a one-line integer parse (^(\d+)) to avoid pullingsemverfor a single comparison.fastify: '5.x'field is removed from thefastify-pluginmetadata so our actionable error wins instead offastify-plugin's. Functionally identical outcome (registration fails on Fastify <5), better message.packages/fastify/src/errors.ts— newincompatibleFastifyVersion(version)builder using the existingcreateErrorMessagehelper so the 🔒 Clerk prefix and docs/discord links stay consistent.packages/fastify/src/test/utils.ts—createFastifyInstanceMockaccepts an optional{ version }override; defaults to'5.8.5'so existing tests are unchanged.packages/fastify/README.md— adds one note in the existing Prerequisites section explaining the@clerk/fastify@^1pin path for Fastify 4 LTS users.patch).Tests
packages/fastify/src/__tests__/clerkPlugin.test.ts:test.each(['4.28.0', '3.29.5', '2.0.0'])— verifies the error fires on multiple sub-5 versions, checks both the version mention and the pin guidance appear in the message, and confirmsdone()is never called.test.each(['5.0.0', '5.8.5', '6.0.0-alpha.1'])— verifies normal registration on supported versions (and the open-ended ≥5 future-proofs against 6.x).All 13 tests in
clerkPlugin.test.tspass locally (the rest of the suite fails on my machine because@clerk/backendworkspace dep isn't built — should pass on CI where workspaces are pre-built).Compatibility