question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

async_hooks.executionAsyncId is not a function

See original GitHub issue

I’m getting the following error when trying to use cls-hooked with Express 4 and Sequelize 4 on node 8.4.0:

TypeError: async_hooks.executionAsyncId is not a function
    at AsyncHook.init (/usr/src/app/node_modules/cls-hooked/context.js:291:32)
    at init (async_hooks.js:444:43)
    at emitInitS (async_hooks.js:314:3)
    at setupInit (internal/process/next_tick.js:225:7)
    at process.nextTick (internal/process/next_tick.js:247:5)
    at onwrite (_stream_writable.js:419:15)
    at Socket._writeGeneric (net.js:770:5)
    at Socket._write (net.js:780:8)
    at doWrite (_stream_writable.js:371:12)
    at writeOrBuffer (_stream_writable.js:357:5)

I have an express middleware that looks like this:

const { createNamespace } = require('cls-hooked')
const shardingNamespace = createNamespace('sharding')

// Patch bluebird to ensure cls context isn't lost
const clsBluebird = require('cls-bluebird')

const Promise = require('bluebird')
clsBluebird(shardingNamespace, Promise)

const sequelizePromise = require('sequelize/lib/promise')
clsBluebird(shardingNamespace, sequelizePromise)

module.exports = function (req, res, next) {
  shardingNamespace.bindEmitter(req)
  shardingNamespace.bindEmitter(res)

  shardingNamespace.run(function () {
    shardingNamespace.set('shard', 'default')
    next()
  })
}

One thing to note is that Sequelize creates its own instance of bluebird via const Promise = require('bluebird').getNewLibraryCopy();. I’m wondering if that’s causing the issue. Putting a console.log(async_hooks.executionAsyncId) before context.js line 291 shows that most of the time it’s a valid function, but occasionally it’s undefined.

Any idea what might be causing this?

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:1
  • Comments:7

github_iconTop GitHub Comments

4reactions
benderTheCrimecommented, Feb 20, 2018

Ok, so this is actually non-trivial. It’s the writing between the lines that’s important here:

https://www.npmjs.com/package/cls-hooked#when-running-nodejs-version--8-this-module-uses-asyncwrap-which-is-an-unsupported-nodejs-api-so-please-consider-the-risk-before-using-it

When running Nodejs version >= 8.2.1, this module uses the newer async_hooks API which is considered Experimental by Nodejs.

This seems fine if I set the check to semver.gte(process.versions.node, '8.2.0') even, NodeJS@8.2.1 is well working as indicated by the README.md. This is also true of 8.3, 8.4, 8.5, 8.6, 8.7, 8.8, and 8.9.

https://www.npmjs.com/package/cls-hooked#when-running-nodejs-version--8-this-module-uses-asyncwrap-which-is-an-unsupported-nodejs-api-so-please-consider-the-risk-before-using-it

When running Nodejs version < 8, this module uses AsyncWrap which is an unsupported Nodejs API, so please consider the risk before using it.

This is also true. I tested with 6.10, 7.3, and they both worked well.

8.1.4 on the other hand does not work well, with either the legacy or the new APIs.

Incidentally, the async_hooks module does exist in NodeJS@8.1.4, it is just missing the executionAsyncId method. This I believe can be replaced with the currentId property. Doing so shows 3-4 failing tests, which is not bad.

@Jeff-Lewis is this something we can consider doing with a switch for the getCurrentId function? Something along the lines of:

const getCurrentId = semver.gte(process.versions.node, '8.2.0') ? async_hooks.getExecutionId : () => async_hooks.currentId;

Looks like it will have to be this way moreso because currentId was deprecated:

https://nodejs.org/api/deprecations.html#deprecations_dep0070_async_hooks_currentid

I’ll dig into the failing test cases in the meantime.

2reactions
Beans0063commented, Oct 11, 2017

I was experiencing this same issue and it resolved by upgrading to 8.6.0

Read more comments on GitHub >

github_iconTop Results From Across the Web

Async hooks | Node.js v19.3.0 Documentation
An easy solution to this when debugging is to use a synchronous logging operation such as fs.
Read more >
Tracking context with async_hooks - node.js - Stack Overflow
This test case will fail because the triggerAsyncId of the promise created when calling next is the executionAsyncId of the Promise.resolve() ...
Read more >
"async_hooks" | typescript - v3.7.7
Useful to store data within the resource. Resource objects returned by executionAsyncResource() are most often internal Node.js handle objects with undocumented ...
Read more >
The power of Async Hooks in Node.js - Medium
An async resource is an object with a callback function associated ... and will not invoke AsyncHooks recursively because it is synchronous.
Read more >
Using Async Hooks for Request Context Handling in Node.js
executionAsyncId (); const trigger_id = async_hooks.triggerAsyncId(); const asyncHook = async_hooks.createHook({ init: function (asyncId, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found