Skip to content

fix(ext/node): use proper error codes for require() invalid arguments#33609

Merged
bartlomieju merged 3 commits into
denoland:mainfrom
Lobster-0429:fix/node-require-invalid-arg-error-types
Apr 28, 2026
Merged

fix(ext/node): use proper error codes for require() invalid arguments#33609
bartlomieju merged 3 commits into
denoland:mainfrom
Lobster-0429:fix/node-require-invalid-arg-error-types

Conversation

@Lobster-0429

Copy link
Copy Markdown

Closes #33607.

Module.prototype.require() previously threw a generic TypeError with no code property when given an invalid argument, breaking compatibility with Node.js code that pattern-matches on error codes. The existing TODO comments in the polyfill already pointed at this fix.

This change aligns with Node.js (lib/internal/modules/cjs/loader.js):

  • Non-string id now throws ERR_INVALID_ARG_TYPE
  • Empty-string id now throws ERR_INVALID_ARG_VALUE with the message
    "must be a non-empty string"

Both error classes were already imported via internalErrors and are used elsewhere in the same file, so no new imports are needed.

Before

require(123)  // TypeError: Invalid argument type   (no .code)
require("")   // TypeError: id must be non empty    (no .code)

After

require(123)  // TypeError [ERR_INVALID_ARG_TYPE]
require("")   // TypeError [ERR_INVALID_ARG_VALUE]

Tests

Added spec test tests/specs/node/require_invalid_arg/ that asserts both error.code and the constructor name for each case.

AI disclosure

Claude Code (Anthropic) was used to assist with drafting the fix, the spec test, and this PR description. All changes were reviewed by the author.

@CLAassistant

CLAassistant commented Apr 27, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@Lobster-0429

Copy link
Copy Markdown
Author

Hi, @bartlomieju,
This is my first contribution to this repository.
Could you please review my PR when you are convenient?
Thank you.

@fibibot fibibot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The substance is right. Verified:

  • internalErrors.ERR_INVALID_ARG_TYPE("id", "string", id) — matches Node's (name, expected, actual) signature, and the class extends NodeTypeError → has the .code = "ERR_INVALID_ARG_TYPE" property and a TypeError prototype chain (via ObjectSetPrototypeOf(this, TypeErrorPrototype) in internal/errors.ts), so e.constructor.name === "TypeError" holds and e.code === "ERR_INVALID_ARG_TYPE" matches.
  • internalErrors.ERR_INVALID_ARG_VALUE("id", id, "must be a non-empty string") — same pattern; matches Node's (name, value, reason) shape.
  • Both classes are already imported via internalErrors (line 129) and used elsewhere in this file (lines 683, 835, 863, 902), so no new imports needed.
  • The two // TODO(bartlomieju): it should use different error type comments that pointed at exactly this fix are correctly removed.
  • Spec test asserts both error.code and error.constructor.name, which is the right shape — would have caught a misnamed code or a non-TypeError-extending class.

Holding off on APPROVE until CI lands — only license/cla and lint title have run so far (this is a first-time external contributor PR; full CI usually needs maintainer authorization to start). I'll re-confirm once test node_compat and test specs finish green.

Welcome and thanks for the AI-disclosure note in the body — appreciated.

@bartlomieju bartlomieju left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks, added two small comments

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you rework this one into a unit test in tests/unit_node/module_test.ts? It will run a lot faster than spawning a subprocess.

const require = createRequire(import.meta.url);

try {
require(123);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It would be nicer to do assertThrows(require(123), ...)

@Lobster-0429

Copy link
Copy Markdown
Author

Hi, @bartlomieju,
Thank you for your attention.
I've just fixed what you want.
Could you please review my PR again?

@bartlomieju bartlomieju left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks

@bartlomieju
bartlomieju enabled auto-merge (squash) April 28, 2026 09:09
@bartlomieju
bartlomieju merged commit e165903 into denoland:main Apr 28, 2026
136 checks passed
@Lobster-0429

Copy link
Copy Markdown
Author

Hi, @bartlomieju,
Thank you for your attention.
Could you please review my another PR?

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.

node: Module.prototype.require() throws plain TypeError instead of ERR_INVALID_ARG_TYPE / ERR_INVALID_ARG_VALUE

4 participants