6

First i use async and await very often and i get this error:

RangeError: Value undefined out of range for undefined options property undefined
    at Set.add (<anonymous>)
    at AsyncHook.init (internal/inspector_async_hook.js:19:25)
    at PromiseWrap.emitInitNative (internal/async_hooks.js:134:43)

And i dont know how i can fix this, i write my code completly in Typescript and i dont created any file that is named 'async_hooks'.

And i dont run more then 10 function async at once i use await very often so it shouldnt stack up but javascript seems not to reduce the asyncId and reach the number limit very fast.

I tried to use less async await but this didnt fix the problem, but the error msg comes later. If i use very less async await i can prevent that this error comes until the function successfully finish the job. (I use Electron 7)

Electron seems to have a very low async pool but it can be reproduced by a default typescript code:

class Test {
    private async testCompare(a,b):Promise<boolean> {
        return a == b;
    }

    public async testRun():Promise<void> {
        for (let index = 0; index < 999999999; index++) {
            for (let index2 = 0; index2 < 999999999; index2++) {
                await this.testCompare(index,index2)
            }
        }
    }

}
new Test().testRun();

This Code produce very much ram usage, and i think i have the same problem in my program. I think that the async pool get filled up until it reached its limit.

18
  • This is not related to async/await. It's an array range error. Can you share a part of your code where this issue occurs? Commented Nov 2, 2019 at 19:45
  • We need to see relevant code in order to help you. As MED said, this has nothing to do with async/await. It looks like you're trying to reference some object property where the object turns out to be undefined. Commented Nov 2, 2019 at 21:10
  • I cant share a "part" of my code because the RangeError comes on every async call, every time a function got called by async get this error pointed at inspector_async_hook.js:19:25 and when i debug it the asyncId get called in an array but the asyncId is too long for an array and throws this error. Commented Nov 2, 2019 at 23:26
  • It takes a while until this error apears, i tried to remove async and await as much as i can and the error didnt come again, if i readd async and await to the functions the error comes back when it runs out of asyncIds. Commented Nov 2, 2019 at 23:40
  • 1
    So, the first thing your code does is create 10^17 promise objects and since they all immediately resolve, it then adds 10^17 events to the event queue for their resolve handlers to get called. Commented Nov 5, 2019 at 19:22

4 Answers 4

14

I got the same error for Set.add as you did once my set size reached 16777216 (2^24). I'm unable to find the info on this limit in the documentation, but I'll assume sets are limited to 16777216 unique values?

Easily tested with a simple for loop.

This will throw the exact same error:

let s = new Set();
for (let i = 0; i <= 16777216; i++) s.add(i);

This will run successfully:

let s = new Set();
for (let i = 0; i < 16777216; i++) s.add(i);

Do note that this will eat up some ~5GB of memory, so increase your heap limit accordingly if it's crashing due to memory restrictions.

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

2 Comments

Same limit for Map
1

Just encountered this using a Set, i used the following as a quick workaround

class Set {
  hash = {}

  add (v) {
    this.hash[JSON.stringify(v)] = true
  }

  has (v) {
    return this.hash[JSON.stringify(v)] == true
  }
}

this has no limit, only limited by your systems memory

Comments

1
RangeError: Value undefined out of range for undefined options property undefined

The above error is caused when a Set hitting the maximum limit of elements. See reference: Maximum number of entries in Node.js Map?

If still run into the problem, you can try large-set, a package that allows you to store and handle a large number of elements without worrying about the 16.777.216 (2^24) limit in a Set by partitions into the smaller sets when it reached the limit, enabling it to store and access more elements than the built-in Set.

But if you don't want to use any package, you can try this small workaround:

class LargeSet {
    constructor(limit = 16777216) {
        this.limit = limit;
        this.sets = [new Set()];
    }

    has(value) {
        return this.sets.some(set => set.has(value));
    }

    add(value) {
        if (this.sets[this.sets.length - 1].size >= this.limit) {
            this.sets.push(new Set());
        }
        if (this.has(value)) return this;
        this.sets[this.sets.length - 1].add(value);
        return this;
    }

    delete(value) {
        for (const set of this.sets) {
          if (set.delete(value)) return true;
        }
        return false;
    }
    
    clear() {
        this.sets = [new Set()];
    }
}

Then test the code:

const largeSet = new LargeSet();
for (let i = 0; i <= 16777216; i++) {
    largeSet.add(i); // No errors will be thrown
}

const set = new Set();
for (let i = 0; i <= 16777216; i++) {
    set.add(i); // Throws a 'RangeError: Value undefined out of range for undefined options property undefined'
}

Comments

0

A workaround for that (as fast as Set) And Unique,

const setA = {};
try {
    for (let i = 0; i < 16777216 + 500; i++) setA[i] = null;
} catch (err) {
    console.log('Died at ', setA.size, ' Because of ');
    console.error(err);
}

console.log('lived even after ', Object.keys(setA).length);

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.