Repository navigation
n-api error status discussion #29849
Description
Activity
If there is an exception pending (whether it was just thrown or not) but no other error then napi_pending_exception should be returned.
If there is a pending exception it is still ok to return a more specific error. The docs say that in addition to handling that error you must still check for a pending exception.
Generally I think we should avoid N-API itself throwing an exception and instead have it return an error. So for:
In which conditions N-APIs should throw JavaScript exceptions? and for those already throwing, which status should be returned? napi_generic_failure or napi_pending_exception?
Either is actually legal. I'd have to look at the specific cases to see if one made more sense than another but my take would be napi_generic_failure as N-API should generally be returning an error as opposed to throwing an exception and returning an error is at least a bit more consistent with that.
@legendecas ideally
- N-API would throw no exceptions of its own.
- If, in the course of interacting with the engine, an exception was thrown, it would return
napi_pending_exception. - Otherwise, if an error condition arose because one of the checks performed by N-API failed, then it would return an appropriate non-
napi_okstatus.
Unfortunately, we have not been very consistent in maintaining this principle as we've moved N-API forward 😕
For example, in
napi_get_property()we haveCHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure);Before returning
napi_generic_failurewe should check whether an exception was thrown and returnnapi_pending_exception.We have quite a few inconsistencies like these in the implementation.
So for question 2:
In which conditions N-APIs should throw JavaScript exceptions? and for those already throwing, which status should be returned? napi_generic_failure or napi_pending_exception?
Could we get into a summary that throwing in N-API shall be prevented from and preferring returning an error napi_status?
For condition of which status shall be returned depends on the case specifically. Likewise, napi_pending_exception shall be preferred if the exception was thrown by the engine. And napi_generic_failure shall be considered in most conditions.
On the statement above, napi_status enum might get appended every time we have a new error condition. E.g. in #29768 two new napi_status were added. Though I am not much uncomfortable with a big enum of napi_status. Would it be concerning anyone?
@legendecas that sounds like a good summary 👍 I don't think there's any problem with a large enum.
I'm not worried about too big an enum either, although I'm not sure it will get all that big anyway.
Just reviewing the error handling in node-addon-api. I noticed that the thrown error in N-APIs with non-
napi_pending_exceptionwould be ignored in https://github.com/nodejs/node-addon-api/blob/master/napi-inl.h#L2006-L2013 (the error would be overriden in https://github.com/nodejs/node-addon-api/blob/master/napi-inl.h#L2023-L2032).So I updated #29847 to correct the related parts. PTAL :)
@legendecas that sounds like a good summary 👍 I don't think there's any problem with a large enum.
So for question 2:
In which conditions N-APIs should throw JavaScript exceptions? and for those already throwing, which status should be returned? napi_generic_failure or napi_pending_exception?
Could we get into a summary that throwing in N-API shall be prevented from and preferring returning an error napi_status?
Absolutely!
For condition of which status shall be returned depends on the case specifically. Likewise, napi_pending_exception shall be preferred if the exception was thrown by the engine. And napi_generic_failure shall be considered in most conditions.
On the statement above, napi_status enum might get appended every time we have a new error condition. E.g. in #29768 two new napi_status were added. Though I am not much uncomfortable with a big enum of napi_status. Would it be concerning anyone?
I don't believe a big enum should be a concern. We have many error scenarios and we should be able to distinguish between them.
The only constraint is that whatever we have today, and however inconsistent it is, must remain so, because we must not introduce breaking changes.
- addednode-apiIssues and PRs related to Node-API.Issues and PRs related to Node-API.
on Oct 18, 2019 - added a commit that references this issue
on Jan 14, 2020 - added a commit that references this issue
on Jan 16, 2020 - added 2 commits that reference this issue
on Mar 14, 2020 @legendecas what's the status of this issue?
This PR has no further action to take. Closing for now.
We could find out that there are several napi_status existing and been used in various n-api functions.
napi_ok:For any n-api call that is successful.
napi_cancelledFor canceled async works.
napi_escape_called_twicenapi_handle_scope_mismatchnapi_callback_scope_mismatchFor handle scope error conditions.
napi_queue_fullnapi_closingFor ThreadSafeFunction error conditions.
napi_invalid_argThis is what I'd like to discuss about. If I got it right, mostly, invalid args of calling of n-api should get into this status, except following type exceptions (mostly JavaScript primitive values, but
arrayanddateare not,nameis a virtual type that is defined in ECMA spec):napi_object_expectednapi_string_expectednapi_name_expectednapi_function_expectednapi_instanceof: would throw JavaScript TypeError if constructor is not a function, and return anapi_function_expectedstatus.napi_number_expectednapi_boolean_expectednapi_array_expectednapi_bigint_expectednapi_date_expectedExcept for all above statuses, following two is additional generic error status:
napi_generic_failureThis could be used in most places IMO, but it has been mixed up with
napi_pending_exceptionin some conditions:THROW_RANGE_ERROR_IF_FALSEreturnsnapi_generic_failurewith throwing JavaScript RangeError.napi_create_bigint_wordsreturnsnapi_pending_exceptionwith throwing JavaScript TypeError.napi_instanceofreturnsnapi_function_expectedwith throwing JavaScript TypeError.napi_create_dataviewreturnsnapi_pending_exceptionwith throwing JavaScript RangeError.napi_pending_exceptionFor any n-api call that has pending JavaScript Exception. If I understand n-api document right, every non-
napi_okstatus should throw a JavaScript exception, andnapi_pending_exceptionshould be used if the previous JavaScript exception was not handled while calling sequent n-apis.So here comes the unresolved questions:
napi_is_<typename>function?napi_generic_failureornapi_pending_exception?Refs: #29768 (comment)
Related: #29847
/cc @gabrielschulhof @mhdawson