gorhill/uBlock · error · Error
Failed to initialize public suffix list.
Error message
Failed to initialize public suffix list.
What it means
StaticNetFilteringEngine.create() initializes the Public Suffix List unless you pass { noPSL: true } (index.js:267). pslInit() (index.js:87) first tries a serialized snapshot at build/publicsuffixlist.json, then falls back to the raw asset assets/thirdparties/publicsuffix.org/list/effective_tld_names.dat; if both are unavailable or empty it returns undefined and create() throws. The PSL is required so the engine can reason about domains and TLDs for network filtering.
Solutions
- If you do not need PSL-based matching, create the engine with `{ noPSL: true }`.
- Ensure build/publicsuffixlist.json is present by running the package's build step (e.g. `npm run build`) before calling create().
- Supply your own PSL data by calling the exported pslInit(rawString) with a non-empty string BEFORE create(); pslInit parses and caches it (index.js:88-90).
- Confirm that assets/thirdparties/publicsuffix.org/list/effective_tld_names.dat ships with your deployment.
Example fix
// before
const engine = await StaticNetFilteringEngine.create(); // throws if PSL data missing
// after (option A: opt out)
const engine = await StaticNetFilteringEngine.create({ noPSL: true });
// after (option B: supply PSL yourself)
import { StaticNetFilteringEngine, pslInit } from 'uBlock'; // exported index.js:291-295
pslInit(myPslText); // parsed & cached when non-empty
const engine = await StaticNetFilteringEngine.create(); Defensive patterns
Strategy: validation
Validate before calling
import { existsSync } from 'fs';
import { resolve } from 'path';
// Probe the two sources pslInit() tries (index.js:97 and index.js:109-112).
const snapshot = resolve(pkgRoot, 'build/publicsuffixlist.json');
const rawList = resolve(pkgRoot, 'assets/thirdparties/publicsuffix.org/list/effective_tld_names.dat');
const pslAvailable = existsSync(snapshot) || existsSync(rawList);
const engine = await StaticNetFilteringEngine.create(
pslAvailable ? {} : { noPSL: true }
); Try / catch
let engine;
try {
engine = await StaticNetFilteringEngine.create();
} catch (err) {
if (err && /public suffix list/i.test(err.message)) {
// Fall back to no-PSL mode only if you can tolerate reduced domain reasoning.
engine = await StaticNetFilteringEngine.create({ noPSL: true });
} else {
throw err;
}
} Prevention
- If PSL-based domain logic is not needed, pass { noPSL: true } from the start.
- Ship build/publicsuffixlist.json and the assets/ PSL data with your bundle.
- Run the package's build step before importing from a source checkout.
- For full control, call the exported pslInit(rawText) with your own PSL data before create().
When it happens
Trigger: Calling create() (or create({})) when build/publicsuffixlist.json is absent AND the effective_tld_names.dat asset is missing or empty. Importing the module from a bundle that excluded the JSON/data files. Running from a source checkout before the build step generates build/publicsuffixlist.json.
Common situations: Bundling with webpack/rollup in a way that drops the package's build/ or assets/ directories; deploying only the JS without the PSL data; a truncated or corrupt effective_tld_names.dat file; fresh source checkout with `npm run build` not yet run.
Related errors
AI-assisted analysis of gorhill/uBlock@c68df492fd (2026-08-12).
Data as JSON: /api/errors/b7db5ef6e873c861.
Report an issue: GitHub.
Appendix: source
Thrown at platform/nodejs/index.js:268
compileList(...args) {
return compileList(...args);
}
async serialize() {
const data = snfe.serialize();
return s14e.serialize(data, { compress: true });
}
async deserialize(serialized) {
const data = s14e.deserialize(serialized);
return snfe.unserialize(data);
}
static async create({ noPSL = false } = {}) {
const instance = new StaticNetFilteringEngine();
if ( noPSL !== true && !pslInit() ) {
throw new Error('Failed to initialize public suffix list.');
}
return instance;
}
static async release() {
if ( snfeProxyInstance === null ) { return; }
snfeProxyInstance = null;
await useLists([]);
}
}
/******************************************************************************/
// rollup.js needs module.exports to be set back to the local exports object.
// This is because some of the code (e.g. publicsuffixlist.js) sets
// module.exports. Once all included files are written like ES modules, using
// export statements, this should no longer be necessary.View on GitHub (pinned to c68df492fd)