Skip to content

Comments

feat: add error handling for FetchError#1634

Open
vmrjnvc wants to merge 1 commit intonpmx-dev:mainfrom
vmrjnvc:feat/add-error-handling-for-fetch-error
Open

feat: add error handling for FetchError#1634
vmrjnvc wants to merge 1 commit intonpmx-dev:mainfrom
vmrjnvc:feat/add-error-handling-for-fetch-error

Conversation

@vmrjnvc
Copy link
Contributor

@vmrjnvc vmrjnvc commented Feb 24, 2026

🔗 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 FetchError handling to handleApiError to forward the upstream HTTP status codes.

@vercel
Copy link

vercel bot commented Feb 24, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
npmx.dev Ready Ready Preview, Comment Feb 24, 2026 11:30pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
docs.npmx.dev Ignored Ignored Preview Feb 24, 2026 11:30pm
npmx-lunaria Ignored Ignored Feb 24, 2026 11:30pm

Request Review

@codecov
Copy link

codecov bot commented Feb 24, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 24, 2026

📝 Walkthrough

Walkthrough

This 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

  • test: add tests for error-handler #1056: Establishes baseline error-handler tests for H3 and Valibot validation handling, providing foundational test coverage that this PR builds upon with FetchError-specific test cases.

Suggested reviewers

  • serhalp
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The pull request description clearly relates to the changeset, describing the addition of FetchError handling to forward upstream HTTP status codes and resolve the badge endpoint issue.
Linked Issues check ✅ Passed The code changes directly address issue #1603 by adding FetchError handling in error-handler.ts to propagate upstream HTTP status codes instead of returning generic 502 errors.
Out of Scope Changes check ✅ Passed All changes are directly scoped to resolving issue #1603: FetchError handling added to error-handler.ts and corresponding test coverage added to error-handler.spec.ts.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c52d259 and 40101c1.

📒 Files selected for processing (2)
  • server/utils/error-handler.ts
  • test/unit/server/utils/error-handler.spec.ts

Comment on lines +22 to +27
if (error instanceof FetchError && error.statusCode) {
throw createError({
statusCode: error.statusCode,
message: error.statusMessage,
})
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n server/utils/error-handler.ts

Repository: 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:

  • statusCodestatus
  • statusMessagestatusText [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 on statusMessage/statusText. [2]

🏁 Script executed:

# Check FetchError type definition and usage in the codebase
rg "FetchError" --type ts --type tsx -B 2 -A 2

Repository: 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 normal Error.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 of status and is read from response.status (it’s undefined if there’s no response). [1]
  • statusMessage?: string — an alias of statusText and is read from response.statusText (it’s undefined if 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.

Suggested change
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,
})
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

No error handling in Badge API

1 participant