44

I am building a CLI tool with node, and want to use the fs.promise API. However, when the app is launched, there's always an ExperimentalWarning, which is super annoying and messes up with the interaction prompts. How can I disable this warning/all warnings?

I'm testing this with the latest node v10 lts release on Windows 10.

To use the CLI tool globally, I have added this to my package.json file:

    { 
      //...
      "preferGlobal": true,
      "bin": { "myapp" : "./index.js" }
      //...
    }

And have run npm link to link the ./index.js script. Then I am able to run the app globally simply with myapp.

After some research I noticed that there are generally 2 ways to disable the warnings:

  1. set environmental variable NODE_NO_WARNINGS=1
  2. call the script with node --no-warnings ./index.js

Although I was able to disable the warnings with the 2 methods above, there seems to be no way to do that while directly running myapp command.

The shebang I placed in the entrance script ./index.js is:

#!/usr/bin/env node


// my code...

I have also read other discussions on modifying the shebang, but haven't found a universal/cross-platform way to do this - to either pass argument to node itself, or set the env variable.

If I publish this npm package, it would be great if there's a way to make sure the warnings of this single package are disabled in advance, instead of having each individual user tweak their environment themselves. Is there any hidden npm package.json configs that allow this?

Any help would be greatly appreciated!

9 Answers 9

37

I configured my test script like this:

 "scripts": {
    "test": "tsc && cross-env NODE_OPTIONS=--experimental-vm-modules NODE_NO_WARNINGS=1 jest"
  },

Notice the NODE_NO_WARNINGS=1 part. It disables the warnings I was getting from setting NODE_OPTIONS=--experimental-vm-modules

Update

Consider using vitest, the Next Generation Testing Framework. I find it much easier to configure. It's also Jest compatible

Sign up to request clarification or add additional context in comments.

Comments

26

I am now using a launcher script to spawn a child_process to work around this limitation. Ugly, but it works with npm link, global installs and whatnot.

#!/usr/bin/env node
const { spawnSync } = require("child_process");
const { resolve } = require("path");

// Say our original entrance script is `app.js`
const cmd = "node --no-warnings " + resolve(__dirname, "app.js");
spawnSync(cmd, { stdio: "inherit", shell: true });

As it's kind of like a hack, I won't be using this method next time, and will instead be wrapping the original APIs in a promise manually, sticking to util.promisify, or using the blocking/sync version of the APIs.

1 Comment

Kind of like a hack? Hackiest hack of all time.
21

You want --disable-warning=ExperimentalWarning

"scripts": {
  "start": "nodemon server.js",
  "test": "winpty node --experimental-vm-modules --disable-warning=ExperimentalWarning node_modules/jest/bin/jest.js"
}

This only suppresses experimental warnings and is thus more specific than the broader --no-warnings

5 Comments

Thank you for this. It was exactly what I was looking for, since disabling every warning is not always desired. And the question did state "this warning" as one of the desires.
Note that this requires Node 21.3.0 or higher
seems to also work in 20.18, although I agree the blog says it's introduced in 21.3.0
I checked the release notes ad this was back ported to 20.11.0
The actual parameter is --no-warnings=ExperimentalWarning. Tested with node.js 22.17.1.
14

I needed to suppress:

ExperimentalWarning: Importing JSON modules is an experimental feature and might change at any time

And this worked for me on Windows, Node.js 18.x:

#!/usr/bin/env node --no-warnings

After install --no-warnings added to node calls inside bin scripts .cmd, .ps

I guess this won't work for Linux. I didn't manage to find universal solution

Related discussions:

1 Comment

This was the quickest and most efficient fix for my situation!
13

New answer: You can also catch emitted warnings in your script and choose which ones to prevent from being logged

const originalEmit = process.emit;
process.emit = function (name, data, ...args) {
  if (
    name === `warning` &&
    typeof data === `object` &&
    data.name === `ExperimentalWarning` 
    //if you want to only stop certain messages, test for the message here:
    //&& data.message.includes(`Fetch API`)
  ) {
    return false;
  }
  return originalEmit.apply(process, arguments);
};

Inspired by this patch to yarn

1 Comment

This was the answer I was looking for. The real solution if you don't manage what spawned the script.
11

You can always remove the warning listener on your running process:

process.removeAllListeners('warning');

You might also recreate a listener (process.on('warning', warning => ...)) that can catch these warnings and give your process a chance to execute some custom behaviors (maybe ignore some, show others...).

Comments

5

Here's what I'm using to run node with a command line flag:

#!/bin/sh
_=0// "exec" "/usr/bin/env" "node" "--experimental-repl-await" "$0" "$@"

// Your normal Javascript here

The first line tells the shell to use /bin/sh to run the script. The second line is a bit magical. To the shell it's a variable assignment _=0// followed by "exec" ....

Node sees it as a variable assignment followed by a comment - so it's almost a nop apart from the side effect of assigning 0 to _.

The result is that when the shell reaches line 2 it will exec node (via env) with any command line options you need.

Comments

0

thanks to @sliverwind who noted the problem only happens in versions below 21.3.0. So the solution, today and going forward, seems to be to simply upgrade to nodejs lts.

Comments

0

I had the same problem not being able to get rid of the warings and when pressing CTRl+C, I got an await toplevel not fulfilled error (because the script was exiting out while awaiting, cathcing errors and more did not work for me).

So updated the script from @Blazing-Fast ( https://stackoverflow.com/a/56095929/1644202 ) and updated it:

#!/usr/bin/env node

import { spawnSync } from 'node:child_process';
import { resolve } from 'node:path';

// Say our original entrance script is `.../index.ts`
const cmd = 'node --no-warnings=ExperimentalWarning "' + resolve(import.meta.dirname, '..', 'index.ts' + '"');
spawnSync(cmd, { stdio: 'inherit', shell: true });

Mind the quotes around the filename: If the path has spaces, it would break otherwise.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.