gorhill/uBlock · error · Error
Pending useLists() operation
Error message
Pending useLists() operation
What it means
useLists() is a re-entrancy-guarded async operation over the shared module-level snfe engine. A module-level flag, useLists.promise (initialized to null at index.js:200), is assigned the in-flight Promise.all while lists compile/load (index.js:191) and reset to null only after that await settles (index.js:193). Invoking useLists() again while the flag is still non-null throws immediately, which prevents two concurrent list-loading passes from racing on the same engine state.
Source
Thrown at platform/nodejs/index.js:161
if ( parser.isFilter() === false ) { continue; }
if ( parser.isNetworkFilter() === false ) { continue; }
if ( compiler.compile(parser, writer) ) { continue; }
if ( compiler.error !== undefined && events !== undefined ) {
options.events.push({
type: 'error',
text: compiler.error
});
}
}
return writer.toString();
}
/******************************************************************************/
async function useLists(lists, options = {}) {
if ( useLists.promise !== null ) {
throw new Error('Pending useLists() operation');
}
// Remove all filters
snfe.reset();
if ( Array.isArray(lists) === false || lists.length === 0 ) {
return;
}
let compiler = null;
const consumeList = list => {
let { compiled } = list;
if ( typeof compiled !== 'string' || compiled === '' ) {
const writer = new CompiledListWriter();
if ( compiler === null ) {
compiler = snfe.createCompiler();
}View on GitHub (pinned to c68df492fd)
Solutions
- Always `await engine.useLists(lists)` before starting a second call; treat list loading as strictly serial.
- Serialize updates with a caller-side queue or mutex so a new request waits for the prior one instead of racing it.
- If you are calling StaticNetFilteringEngine.release(), make sure no earlier useLists() is still pending, since release awaits useLists([]) internally.
- Resolve list entry contents before invoking rather than passing live Promises, so the batch settles predictably.
Example fix
// before engine.useLists(lists); // not awaited engine.useLists(otherLists); // throws: Pending useLists() operation // after await engine.useLists(lists); await engine.useLists(otherLists); // strictly serial
Defensive patterns
Strategy: validation
Validate before calling
// Serialize list loads at the caller; never overlap useLists() calls.
let pending = null;
async function safeUseLists(engine, lists) {
if (pending) await pending; // wait for prior load to settle
const p = engine.useLists(lists);
pending = p;
try { return await p; }
finally { pending = null; }
} Try / catch
// Catch only to surface that a load is in flight; do NOT blindly retry the
// same call, which can re-trigger the guard. Serialize and await first.
try {
await engine.useLists(lists);
} catch (err) {
if (err && /Pending useLists\(\) operation/.test(err.message)) {
throw new Error('List load already in progress; await it before retrying.');
}
throw err;
} Prevention
- Treat engine.useLists() as strictly serial: always await it before the next call.
- Keep a single caller-side pending flag/queue so updates never overlap.
- Resolve list entry contents to plain objects before passing them in.
- Before calling StaticNetFilteringEngine.release(), ensure no useLists() is still running.
When it happens
Trigger: Calling engine.useLists(lists) a second time before the first awaited call has settled. The instance method delegates straight to the module-level useLists (index.js:216), so any overlap trips the guard. It also fires when list entries are themselves unresolved Promises: the loop wraps each in Promise.resolve (index.js:187-189), so the overall Promise.all stays pending and a second useLists() call lands while it is in flight.
Common situations: Reloading filter lists from an event handler without awaiting the previous reload; dispatching two updates in quick succession; calling engine.useLists() fire-and-forget; or calling StaticNetFilteringEngine.release() (which itself awaits useLists([]) at index.js:277) while another load is still running.
Related errors
AI-assisted analysis of gorhill/uBlock@c68df492fd (2026-08-12).
Data as JSON: /api/errors/6f5d39d12878a056.
Report an issue: GitHub.