Skip to content

Node API: napi_is_exception_pending returned true after successfully calling napi_get_and_clear_last_exception #61290

@ruochenjia

Description

@ruochenjia

Version

v24.12.0

Platform

Linux xubuntu 6.12.63-0 #1 SMP PREEMPT_DYNAMIC Wed Dec 31 19:18:53 GMT 2025 x86_64 GNU/Linux

Subsystem

No response

What steps will reproduce the bug?

  1. Create a c++ addon using Node API with the following code and export the test function to JS code:
#define check_status(e) (__builtin_expect((e) == napi_status::napi_ok, 1) ? void(0) : __builtin_trap())

int test_op(napi_env env, napi_value cb) noexcept {
	// some native operations
	// ...

	// invoke js callback
	int status;

	{
		napi_value js_undefined;
		check_status(napi_get_undefined(env, &js_undefined));

		// unchecked for js exceptions
		status = napi_call_function(env, js_undefined, cb, 0, nullptr, nullptr);
	}

	// some cleanup tasks
	// ...

	return status;
}

napi_value test(napi_env env, napi_callback_info info) noexcept {
	// get function arguments
	size_t argc = 1; napi_value arg0; napi_value object;
	check_status(napi_get_cb_info(env, info, &argc, &arg0, &object, nullptr));

	// arguments type check
	napi_valuetype type;
	check_status(napi_typeof(env, arg0, &type));

	if (type != napi_valuetype::napi_function) {
		// throw invalid arguments
		return nullptr;
	}

	// invoke native functions and js callback
	int code = test_op(env, arg0);

	// check for errors
	if (code != 0) {
		napi_value err;
		check_status(napi_get_and_clear_last_exception(env, &err));

		if (napi_coerce_to_string(env, err, &err) == napi_status::napi_ok) {
			// print verbose error message based on string output
		} else {
			// print generic error message
		}

		bool z;
		check_status(napi_is_exception_pending(env, &z));
		_assert(!z); // <-- Assertion error occurs here
	}

	return js_undefined(env);
}
  1. Run the following JS code:
const mod = require("./module.node");

mod.test(() => {
  throw { __proto__: null }
});

How often does it reproduce? Is there a required condition?

This error always occurs and has been tested with different versions of Node.js. However this only happens for errors thrown in JS callback functions that are not instance of the Error class. It does not happen for errors triggered on the native side with napi_throw_error.

What is the expected behavior? Why is that the expected behavior?

The boolean value returned by napi_is_exception_pending should be false if napi_get_and_clear_last_exception returned a napi_ok status code, and the function should return without triggering an assertion error.

What do you see instead?

An assertion error is triggered at the line _assert(!z); and the program terminates.

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    node-apiIssues and PRs related to the Node-API.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions