Skip to content

fix: ctx.assert() throws HttpError instances (#1925)#1942

Open
guoyangzhen wants to merge 1 commit intokoajs:masterfrom
guoyangzhen:fix/assert-httperror-instanceof
Open

fix: ctx.assert() throws HttpError instances (#1925)#1942
guoyangzhen wants to merge 1 commit intokoajs:masterfrom
guoyangzhen:fix/assert-httperror-instanceof

Conversation

@guoyangzhen
Copy link
Copy Markdown

Summary

Fixes #1925

ctx.assert() throws errors from http-assert's own http-errors dependency, not koa's. This means err instanceof HttpError returns false when catching errors from ctx.assert(), even though the JSDoc says it throws HttpError.

Root Cause

http-assert imports its own copy of http-errors in its node_modules. Even though both use the same package version, they're separate module instances, so instanceof fails.

Fix

Wrap http-assert in context.js to catch thrown errors and re-throw them using koa's own createError. This ensures:

  1. err instanceof HttpError works correctly
  2. All http-assert sub-methods (equal, deepEqual, etc.) are preserved
  3. The error status and message are maintained

Example

try {
  ctx.assert(false, 401, 'Unauthorized')
} catch (e) {
  console.log(e instanceof HttpError) // Now: true ✅ (was: false ❌)
}

Wrap http-assert to re-throw errors using koa's own http-errors,
so instanceof HttpError checks work correctly.

Fixes koajs#1925
@guoyangzhen
Copy link
Copy Markdown
Author

Hi, just checking in on this PR. Happy to make any changes if needed. Thanks!

@guoyangzhen
Copy link
Copy Markdown
Author

Hi! Any chance this could get a review? The fix is straightforward and tests pass. Happy to adjust if needed.

Copy link
Copy Markdown
Author

@guoyangzhen guoyangzhen left a comment

Choose a reason for hiding this comment

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

The CI failure is because http-errors@2.0.1's createError(status, msg, opts) throws a TypeError when opts is undefined.

The fix for wrappedAssert:

function wrappedAssert (value, status, msg, opts) {
  try {
    httpAssert(value, status, msg, opts)
  } catch (err) {
    if (err instanceof HttpError) {
      throw err
    }
    const args = [err.status || err.statusCode || 500, err.message || msg]
    if (opts) args.push(opts)
    throw createError(...args)
  }
}

The issue: when ctx.assert(false, 404, 'custom message') is called without a 4th arg, opts is undefined, and createError(404, msg, undefined) throws TypeError: argument #3 unsupported type undefined instead of creating the HttpError.

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.

[fix] ctx.assert() throws specific error classes

1 participant