Uniformly generate a number from 0 to n-1 that isn't on a blacklist
The problem is backwards. You would never present a exclusion list for random values, rather you would present a list to randomly pick from.
Anyways to fit the problem.
Two ways this can be done

Guessing
Deterministically

Guessing
Your method use a random guess, you guess that the number is not in the list. If it is you guess again. This works well when the list contains only a small set of the numbers.
However when the exclusion list gets larger you need to make more guess to find one that is not in the list. The number of guess grows very fast as your exclusion list gets closer to excluding all.
This is the worst possible performance at \$O(m^{-(1/n)})\$ it has an Infinity
The other problem with guessing is that you can not know how long the function is going to run for. This makes it totally unsuitable for many real time applications.
Deterministically
You can improve the overall performance and have a function that has a known fixed time to get a result.
However is is much slower when the exclusion list is relatively small.
The performance is linear at \$O(n)\$
If the exclusion set does not change between calls it get even less complex at \$O(1)\$ which is the best you can get.
Example
The \$O(n)\$ solution
It returns undefined if it can not find a number rather than throw. You should not be solving the calling function problems as the other answers suggest.
const getRandNotInList = (n, list) =&gt; {
    const picks = [];
    const getPickable = () =&gt; {
        var i = 0; dir = Math.sign(n);
        list = new Set(list);
        while (i !== n) {
            !list.has(i) &amp;&amp; picks.push(i);
            i += dir;
        }
    }
    n = Math.floor(n);        
    if (n === 0) { return list.includes(0) ? undefined : 0 }
    getPickable();
    return picks[Math.random() * picks.length | 0]; // (| 0) same as Math.floor 
                                                    // (only for positive ints).
}