feat: add error handling for FetchError#1634
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
2 Skipped Deployments
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
📝 WalkthroughWalkthroughThis pull request adds handling for FetchError exceptions in the error handler utility. The implementation detects when an error is an instance of FetchError and contains a statusCode, then converts it to an H3 error using that statusCode and corresponding statusMessage. The changes include an import of FetchError from the ofetch library and placement of this logic before Valibot validation handling within the error processing flow. Supporting test cases verify that statusCode and statusMessage are correctly propagated from FetchError instances, including fallback behaviour when statusCode is absent. Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
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 |
| if (error instanceof FetchError && error.statusCode) { | ||
| throw createError({ | ||
| statusCode: error.statusCode, | ||
| message: error.statusMessage, | ||
| }) | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n server/utils/error-handler.tsRepository: npmx-dev/npmx.dev
Length of output: 1671
🌐 Web query:
h3 v1.15.5 createError API documentation statusMessage field HTTP response
💡 Result:
In h3 v1.x (including v1.15.5), createError({ statusCode, statusMessage, ... }) uses statusMessage as the HTTP “reason phrase” (the text part of 400 Bad Request, 404 Not Found, etc.)—i.e., what Node exposes as http.ServerResponse.statusMessage. The error sender sets the outgoing response’s statusCode and statusMessage, and also serializes statusMessage into the default JSON error body. [3]
createError’s v1-era shape is documented/advertised in the package README as createError({ statusCode, statusMessage, data? }). [4]
However, the project is moving to Web API naming:
statusCode→statusstatusMessage→statusText[1]
And current H3 docs emphasize throwing HTTPError with status + statusText (sent in the response header) and message (sent in the JSON body). [2]
Also note: many environments (notably HTTP/2) don’t reliably support transmitting a reason phrase/status text, so clients may see it missing/empty even if you set it server-side. [5]
Practical guidance
- If you want a client-visible, reliable message: put it in the JSON body (
message/data) rather than relying onstatusMessage/statusText. [2]
🏁 Script executed:
# Check FetchError type definition and usage in the codebase
rg "FetchError" --type ts --type tsx -B 2 -A 2Repository: npmx-dev/npmx.dev
Length of output: 88
🌐 Web query:
ofetch FetchError interface properties statusCode statusMessage message
💡 Result:
In ofetch, FetchError extends the built-in Error, and the properties you mentioned behave like this:
message: string— the normalError.message, built by ofetch as a human-readable string that includes the HTTP method, request URL, and (if there is a response)response.status+response.statusText(plus any underlying error message if present). [1]statusCode?: number— an alias ofstatusand is read fromresponse.status(it’sundefinedif there’s no response). [1]statusMessage?: string— an alias ofstatusTextand is read fromresponse.statusText(it’sundefinedif there’s no response). [1]
You’ll also commonly see (related) properties like status?: number, statusText?: string, data?: any (parsed error body), and response?: FetchResponse on the same error. [1], [2]
Sources: [1] [2]
Align FetchError handler with h3 createError pattern by passing statusMessage field.
The FetchError handler (lines 22–27) omits the statusMessage field when calling createError, inconsistent with the fallback handler (lines 39–43) and h3 error handling pattern (lines 12–19). The h3 createError API uses statusMessage for the HTTP reason phrase and message for the JSON response body; passing only message: error.statusMessage loses this distinction.
Suggested patch
if (error instanceof FetchError && error.statusCode) {
throw createError({
statusCode: error.statusCode,
- message: error.statusMessage,
+ statusMessage: error.statusMessage,
+ message: error.statusMessage ?? error.message,
})
}📝 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.
| if (error instanceof FetchError && error.statusCode) { | |
| throw createError({ | |
| statusCode: error.statusCode, | |
| message: error.statusMessage, | |
| }) | |
| } | |
| if (error instanceof FetchError && error.statusCode) { | |
| throw createError({ | |
| statusCode: error.statusCode, | |
| statusMessage: error.statusMessage, | |
| message: error.statusMessage ?? error.message, | |
| }) | |
| } |
🔗 Linked issue
Resolves #1603
📚 Description
Badge and other registry endpoints were returning 502 instead of 404 when a package didn't exist on npm. Added
FetchErrorhandling tohandleApiErrorto forward the upstream HTTP status codes.