javascriptnode.jsdropboxunhandled-exceptionunhandled-promise-rejection

Dropbox's `filesGetTemporaryLink` throws an uncatchable `UnhandledPromiseRejectionWarning` and terminates Node.js


To get a download link to the file hosted on Dropbox, I'm using a Dropbox JavaScript API (7.0.0):

export const fileDownload = async function fileDownload(fileUUID) {

    let isSucceeded;
    let message;
    let file;
    const dbx = _dropboxFactory();

    try {
        const operationResult = await dbx.filesGetTemporaryLink({
            path: `/${CONFIG_STORAGE.uploader.assetsPath}/${fileUUID}`
        });

        if ("OK" === http.STATUS_CODES[operationResult.status].toUpperCase()) {

            file = Object.freeze({
                length: operationResult?.result?.metadata?.size,
                link: operationResult?.result?.link,
                mime: mime.lookup(operationResult?.result?.metadata?.name),
                name: operationResult?.result?.metadata?.name
            });
            isSucceeded = true;
            message = SYS_MESSAGES.storageFileDownloadSucceeded.code;

        } else {
            isSucceeded = false;
            message = SYS_MESSAGES.storageFileDownloadFailed.code;
        }
    } catch (err) {
        file = "error";
        isSucceeded = false;
        message = "FIL_NOT_FOUND";
    }

    const downloadResult = Object.freeze({
        file,
        isSucceeded,
        message
    });

    return downloadResult;

};

The problem is that when the path to the file is wrong, I get a Node.js exception:

(node:9156) UnhandledPromiseRejectionWarning: #<Object>

(node:9156) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)

(node:9156) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

I've tested several options and came to conclusion that the issue is in:

const operationResult = await dbx.filesGetTemporaryLink({
    path: `/${CONFIG_STORAGE.uploader.assetsPath}/${fileUUID}`
});

My questions:

  1. Why does Node.js claim «unhandled promise rejection» or «promise which was not handled with .catch()» and throws an UnhandledPromiseRejectionWarning exception if the code, which generates it is wrapped by try-catch?

  2. Starting Node.js 15.x.x, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. Therefore, how to avoid UnhandledPromiseRejectionWarning?

A temporal workaround:

To run Node.js with a flag --unhandled-rejections=warn.
This will prevent the termination of the Node.js process with a non-zero exit code upon UnhandledPromiseRejectionWarning.


Solution

  • The problem was in the Dropbox library and has been solved by the Dropbox team with the release of 7.1.0. After upgrading the code in the question works correctly.