web3.js icon indicating copy to clipboard operation
web3.js copied to clipboard

MaxListenersExceededWarning in 4.X

Open M0cK1nG-b1Rd opened this issue 2 years ago • 9 comments

hello, I am using web3.js of 4.2.0 to listen both pending and confirmed transactions. I get the warning of (node:3862464) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 message listeners added to [EventEmitter]. Use emitter.setMaxListeners() to increase limit when my code runs for a while. My code looks like

    async function pendingSubscription() {
        const subscription = await web3.eth.subscribe('pendingTransactions');
        subscription.on('connect', async () => {
            console.log("Scanning mempool...");
        })
        // note that in version 4.x the way you get notified for `data` and `error` has changed
        subscription.on('data', async (txHash) => {
            hashQ.add(txHash)
            checkTransaction(txHash);
        });
        subscription.on('error', (err) => {
            console.log(err);
        });
    }

    async function confirmedSubscription() {
        const subscription = await web3.eth.subscribe('newBlockHeaders');
        subscription.on('connect', async () => {
            console.log("Meanwhile listening for new blocks...");
        })
        // note that in version 4.x the way you get notified for `data` and `error` has changed
        subscription.on('data', async (blockHeader) => {
            processBlock(blockHeader.number);
        });
        subscription.on('error', (err) => {
            console.log(err);
        });
    }

    confirmedSubscription();
    pendingSubscription();

and here is my code when initializing web3 project, I try to use setMaxListenerWarningThreshold as mentioned in #1494, but in vain. Can someone help?

let web3 = new Web3(process.env.websocket);
web3.eth.handleRevert = true;
// no use
web3.eth.setMaxListenerWarningThreshold(50);
// no use
web3.setMaxListenerWarningThreshold(50);
// no use
web3.maxListenersWarningThreshold = 100;
// no use
web3.eth.maxListenersWarningThreshold = 100;

M0cK1nG-b1Rd avatar Oct 28 '23 08:10 M0cK1nG-b1Rd

seems issue in setting Warning Threshold. We will investigate and fix.

jdevcs avatar Oct 30 '23 17:10 jdevcs

Hello @M0cK1nG-b1Rd, Could you please provide more info about your environment? Are you using nodejs? What is your exact project setup? Could you please refer to a repo or better a link to a Cloud IDE like https://codesandbox.io/? Thanks,

Muhammad-Altabba avatar Nov 02 '23 09:11 Muhammad-Altabba

hey, I am currently using nodejs of version 18.17.1, and here are my other dependencies.

    "@ethereumjs/common": "^4.0.0",
    "@ethereumjs/tx": "^5.0.0",
    "@ethereumjs/util": "^9.0.0",
    "async": "^3.2.4",
    "axios": "^1.5.1",
    "bignumber.js": "^9.1.2",
    "bn.js": "^5.2.1",
    "cheerio": "^1.0.0-rc.12",
    "clear": "^0.1.0",
    "colors": "^1.4.0",
    "decimal.js": "^10.4.3",
    "dotenv": "^16.3.1",
    "ethers": "^6.8.0",
    "moralis": "^2.23.1",
    "node-cron": "^3.0.2",
    "pkg": "^5.8.1",
    "prompt-sync": "^4.2.0",
    "silly-datetime": "^0.1.2",
    "web3": "^4.2.0"

I think it's rather difficult to refer to a cloud ide because I am currently using web3js to interact with bsc mainnet via a self-build bsc node on my server. It's rather hard to reproduce the whole environment. Is there any alternatives?

M0cK1nG-b1Rd avatar Nov 03 '23 09:11 M0cK1nG-b1Rd

Thanks @M0cK1nG-b1Rd, We will try to reproduce. However, I also need a confirmation from you whether you are using the EventEmitter class anywhere in you code? I mean beside using web3.js, do you use EventEmitter somewhere? Thanks,

Muhammad-Altabba avatar Nov 05 '23 18:11 Muhammad-Altabba

heyyy, seems I made a mistake. I use --trace-warnings to dig more about the warnings and it turns out it's somewhere else that triggers the warning. But it is still within web3.js.

(node:333935) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 message listeners added to [EventEmitter]. Use emitter.setMaxListeners() to increase limit
    at _addListener (node:events:588:17)
    at EventEmitter.addListener (node:events:606:10)
    at WebSocketProvider.on (/home/test/node_modules/web3-utils/lib/commonjs/socket_provider.js:123:28)
    at Web3SubscriptionManager.listenToProviderEvents (/home/test/node_modules/web3-core/lib/commonjs/web3_subscription_manager.js:59:46)
    at new Web3SubscriptionManager (/home/test/node_modules/web3-core/lib/commonjs/web3_subscription_manager.js:47:14)
    at new Web3Context (/home/test/node_modules/web3-core/lib/commonjs/web3_context.js:42:41)
    at new Contract (/home/test/node_modules/web3-eth-contract/lib/commonjs/contract.js:82:9)
    at new ContractBuilder (/home/test/node_modules/web3/lib/commonjs/web3.js:103:21)
    at checkSingleToken (/home/test/pancakeWork.js:4428:33)

and my checkSingleToken has nothing special, just

const checkSingleToken = async (newTokenInfo, tokenAddress) => {
    if (newTokenInfo.safe == 6) {
        try {
            const owner = await new Contract(standardTokenAbi, tokenAddress, web3).methods.owner().call();
            newTokenInfo.owner = owner.toLowerCase();
        } catch (error) {
        }
    }
    worker.postMessage({ "action": "checkSingleTokenIsSafe", "data": newTokenInfo });
};

the trace indicates that the warning comes from const owner = await new Contract(standardTokenAbi, tokenAddress, web3).methods.owner().call(); Also the code to set threshold like web3.setMaxListenerWarningThreshold(50); didn't help. I also try to upgrade node version to 20.9.0 and it didn't works.

BTW, This code is originally used in web3.js of version 1.X, I do the upgrade and not sure if I handle this correctly, from

const owner = await new web3.eth.Contract(standardTokenAbi, tokenAddress).methods.owner().call();

to

const owner = await new Contract(standardTokenAbi, tokenAddress, web3).methods.owner().call();

For this, I recheck my code and I am sure I am not using EventEmitter somewhere else.

Thanks @M0cK1nG-b1Rd, We will try to reproduce. However, I also need a confirmation from you whether you are using the EventEmitter class anywhere in you code? I mean beside using web3.js, do you use EventEmitter somewhere? Thanks,

M0cK1nG-b1Rd avatar Nov 06 '23 15:11 M0cK1nG-b1Rd

Thanks @M0cK1nG-b1Rd, Could you please also share the full code so we can reproduce? You may share a github repository or better to share on some Cloud IDE like https://codesandbox.io/, for example.

Muhammad-Altabba avatar Jan 05 '24 07:01 Muhammad-Altabba

Thanks @M0cK1nG-b1Rd, Could you please also share the full code so we can reproduce? You may share a github repository or better to share on some Cloud IDE like https://codesandbox.io/, for example.

heyy, I create a minimun test case to stablely reproduce the problem in https://github.com/M0cK1nG-b1Rd/web3js_reproduce, might need a bsc node to run the script

M0cK1nG-b1Rd avatar Jan 07 '24 15:01 M0cK1nG-b1Rd

Thanks @M0cK1nG-b1Rd I am facing issues when trying to run BSC inside a docker: https://github.com/bnb-chain/bsc-docker/issues/15 Do you run the node natively or inside a docker container? What guide do you recommend to follow to run the node using docker?

Muhammad-Altabba avatar Jan 07 '24 19:01 Muhammad-Altabba

Thanks @M0cK1nG-b1Rd I am facing issues when trying to run BSC inside a docker: bnb-chain/bsc-docker#15 Do you run the node natively or inside a docker container? What guide do you recommend to follow to run the node using docker?

I run the node natively and I am not so familiar with bsc inside docker. Building a node yourself occupies so many server resources so I actually recommend using some third party node provider, as long as it supports wss. I tried quicknode and it can also reproduce this issue. Setup a bsc node in quicknode dashboard and choose free plan will be just ok.

M0cK1nG-b1Rd avatar Jan 08 '24 02:01 M0cK1nG-b1Rd

Hi @M0cK1nG-b1Rd , I am happy to tell you that this issue has been resolved in the later versions of web3.js. So, you just need to update your web3.js dependency to the latest.

However, if you updated to the latest (4.5.0) and you are still facing this issue. Feel free to reopen it. And if you faced a different issue, you can open a new issue for that.

And a note on the side, you do not need to instantiate new Contract instance everytime you are calling a contract method. so instead of having:

const checkSingleToken = async (newTokenInfo, tokenAddress) => {
    if (newTokenInfo.safe == 6) {
        try {
            const owner = await new Contract(standardTokenAbi, tokenAddress, web3).methods.owner().call();
            newTokenInfo.owner = owner.toLowerCase();
        } catch (error) {
        }
    }
    worker.postMessage({ "action": "checkSingleTokenIsSafe", "data": newTokenInfo });
};

You can have:

const myContract = new Contract(standardTokenAbi, tokenAddress, web3);
const checkSingleToken = async (newTokenInfo, tokenAddress) => {
    if (newTokenInfo.safe == 6) {
        try {
            const owner = await myContract.methods.owner().call();
            newTokenInfo.owner = owner.toLowerCase();
        } catch (error) {
        }
    }
    worker.postMessage({ "action": "checkSingleTokenIsSafe", "data": newTokenInfo });
};

Muhammad-Altabba avatar Feb 20 '24 08:02 Muhammad-Altabba

Hi @M0cK1nG-b1Rd , 你好, I am happy to tell you that this issue has been resolved in the later versions of web3.js. So, you just need to update your web3.js dependency to the latest.我很高兴地告诉您,这个问题在 web3.js 的更高版本中已经得到解决。因此,您只需将 web3.js 依赖项更新到最新即可。

However, if you updated to the latest (4.5.0) and you are still facing this issue. Feel free to reopen it. And if you faced a different issue, you can open a new issue for that.但是,如果您更新到最新版本(4.5.0)并且仍然面临此问题。请随意重新打开它。如果您遇到不同的问题,您可以为此打开一个新问题。

And a note on the side, you do not need to instantiate new Contract instance everytime you are calling a contract method.另外需要注意的是,您不需要每次调用合约方法时都实例化新的 Contract 实例。 so instead of having:所以不要有:

const checkSingleToken = async (newTokenInfo, tokenAddress) => {
    if (newTokenInfo.safe == 6) {
        try {
            const owner = await new Contract(standardTokenAbi, tokenAddress, web3).methods.owner().call();
            newTokenInfo.owner = owner.toLowerCase();
        } catch (error) {
        }
    }
    worker.postMessage({ "action": "checkSingleTokenIsSafe", "data": newTokenInfo });
};

You can have: 你可以有:

const myContract = new Contract(standardTokenAbi, tokenAddress, web3);
const checkSingleToken = async (newTokenInfo, tokenAddress) => {
    if (newTokenInfo.safe == 6) {
        try {
            const owner = await myContract.methods.owner().call();
            newTokenInfo.owner = owner.toLowerCase();
        } catch (error) {
        }
    }
    worker.postMessage({ "action": "checkSingleTokenIsSafe", "data": newTokenInfo });
};

My code is written like this, using web3js version 4.5.0, and I still receive this warning: (node:1) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 error listeners added to [ClientHttp2Session]. Use emitter.setMaxListeners() to increase the limit (Use node --trace-warnings ... to show where the warning was created).

this.web3 = new Web3(new Web3.providers.WebsocketProvider(providerUrl));
        this.contracts = contractConfig.map((config) => {
            return new this.web3.eth.Contract(config[1].abi, config[0]);
        });
this.contracts.forEach((contract) => {
            console.log(`[${new Date().toLocaleString()}] EventListener listening contractAddress ${contract.options.address} start...`);
            contract.events.allEvents(
                {fromBlock: process.env.FROM_BLOCK}
            )
                .on('data', (event) => {
                    // ...
                })
        });

baixiang0101 avatar May 28 '24 11:05 baixiang0101