gorhill/uBlock · error · Error
Only a single instance is supported.
Error message
Only a single instance is supported.
What it means
StaticNetFilteringEngine is a singleton-by-design proxy over the shared module-level snfe engine. The constructor captures the first instance into the module-level snfeProxyInstance (index.js:212); a subsequent `new StaticNetFilteringEngine()` finds it non-null and throws (index.js:209). The slot is cleared only by StaticNetFilteringEngine.release() (index.js:276), so only one engine can live in a process at a time.
Source
Thrown at platform/nodejs/index.js:210
await useLists.promise;
useLists.promise = null;
// Commit changes
snfe.freeze();
snfe.optimize();
}
useLists.promise = null;
/******************************************************************************/
const fctx = new FilteringContext();
let snfeProxyInstance = null;
class StaticNetFilteringEngine {
constructor() {
if ( snfeProxyInstance !== null ) {
throw new Error('Only a single instance is supported.');
}
snfeProxyInstance = this;
}
useLists(lists) {
return useLists(lists);
}
matchRequest(details) {
return snfe.matchRequest(fctx.fromDetails(details));
}
matchAndFetchModifiers(details, modifier) {
return snfe.matchAndFetchModifiers(fctx.fromDetails(details), modifier);
}
hasQuery(details) {
return snfe.hasQuery(details);View on GitHub (pinned to c68df492fd)
Solutions
- Reuse the single instance returned by the first create() and update lists via its useLists() method rather than recreating.
- Call `await StaticNetFilteringEngine.release()` before creating a new instance; release nulls snfeProxyInstance and resets lists.
- In test suites, create once in beforeAll and call release() in afterAll, never per-test without teardown.
- If you truly need two independent engines in one process, isolate them in separate child processes or worker threads.
Example fix
// before const engine = await StaticNetFilteringEngine.create(); const engine2 = await StaticNetFilteringEngine.create(); // throws: single instance // after const engine = await StaticNetFilteringEngine.create(); await engine.useLists(lists); // update in place await StaticNetFilteringEngine.release(); // free the singleton const fresh = await StaticNetFilteringEngine.create(); // now ok
Defensive patterns
Strategy: validation
Validate before calling
// Cache and reuse the singleton; release() before creating a new one.
let engine = null;
async function getEngine() {
if (engine) return engine;
engine = await StaticNetFilteringEngine.create();
return engine;
}
async function replaceEngine() {
await StaticNetFilteringEngine.release(); // clears snfeProxyInstance
engine = null;
return getEngine();
} Try / catch
// If a second create() may race (e.g. warm serverless), catch and reuse/release.
let engine = null;
async function once(fn) {
if (engine) return engine;
try {
engine = await StaticNetFilteringEngine.create();
return engine;
} catch (err) {
if (err && /single instance/i.test(err.message)) {
await StaticNetFilteringEngine.release();
engine = await StaticNetFilteringEngine.create();
return engine;
}
throw err;
}
} Prevention
- Create the engine once and reuse it; update lists via useLists() instead of recreating.
- Always pair creation with StaticNetFilteringEngine.release() in teardown.
- In tests, use beforeAll/afterAll rather than per-test creation without release.
- Run genuinely independent engines in separate processes or worker threads.
When it happens
Trigger: Calling StaticNetFilteringEngine.create() twice without release() in between (create calls the constructor at index.js:265). Directly invoking `new StaticNetFilteringEngine()` a second time. Hot-reloading the module in a long-lived process without releasing the prior instance first.
Common situations: Test suites that spin up a fresh engine per case without teardown; calling create() again after an earlier call threw, on the assumption the failed instance was never registered; serverless warm reuse where module state persists across invocations; recreating the engine instead of updating its lists.
Related errors
AI-assisted analysis of gorhill/uBlock@c68df492fd (2026-08-12).
Data as JSON: /api/errors/a57851afa4791fbf.
Report an issue: GitHub.