GrapesJS/grapesjs · error
Plugin ${explicitId} not found
Error message
Plugin ${explicitId} not found What it means
The plugin manager resolves plugins by id from registered plugins. If a plugin was added by explicit id (e.g. via `plugins: ['my-plugin']` with `pluginsOpts` or an explicit id) and cannot be resolved to a function plugin, it throws `Plugin ${id} not found` instead of just warning.
Source
Thrown at packages/core/src/plugin_manager/index.ts:63
const { plugin } = unwrapPluginMeta(target as Plugin<any>);
if (!isPluginFunction(plugin)) return;
return this.getAll().find((item) => item.get('plugin') === plugin);
}
private normalizePlugin(input: PluginInput, options: PluginOptions = {}) {
const descriptor = isPluginDescriptor(input) ? input : undefined;
const sourcePlugin = (descriptor ? descriptor.plugin : input) as string | Plugin<any>;
const explicitId = descriptor?.id || '';
const unwrapped = unwrapPluginMeta(sourcePlugin);
const resolvedPlugin = getPlugin(unwrapped.plugin);
let normalized;
if (!resolvedPlugin || !isPluginFunction(resolvedPlugin)) {
const pluginId = isString(unwrapped.plugin) ? unwrapped.plugin : getPluginId(unwrapped.plugin) || explicitId;
if (explicitId) {
throw new Error(`Plugin ${explicitId} not found`);
}
logPluginWarn(this.editor, pluginId || 'unknown');
} else {
const id = explicitId || this.resolvePluginId(sourcePlugin, resolvedPlugin);
normalized = {
id,
plugin: resolvedPlugin,
options: {
...this.getConfigPluginOptions(id, sourcePlugin),
...unwrapped.options,
...options,
},
};
}
return normalized;
}
View on GitHub (pinned to 2bdeda85b8)
Solutions
- Import the plugin and pass the function directly: `plugins: [myPlugin]` or `plugins: [[myPlugin, opts]]`.
- Register by id first: `grapesjs.plugins.add('my-plugin', myPlugin)` then use the string id.
- Verify the plugin package is installed/imported and the id spelling matches exactly.
- Check the plugin supports your GrapesJS major version (v3 vs v4 plugin signature).
Example fix
// before
const editor = grapesjs.init({ plugins: ['gjs-blocks-basic'] }); // never registered
// after
import blocksBasic from 'grapesjs-blocks-basic';
const editor = grapesjs.init({ plugins: [blocksBasic] }); Defensive patterns
Strategy: type-guard
Validate before calling
const resolved = typeof plugin === 'string' ? grapesjs.plugins.get?.(plugin) : plugin;
if (typeof resolved !== 'function') {
throw new Error(`Plugin ${plugin} is not loaded; import it or call grapesjs.plugins.add()`);
} Type guard
function isLoadedPlugin(p) {
return typeof p === 'function' || (Array.isArray(p) && typeof p[0] === 'function');
} Try / catch
try {
const editor = grapesjs.init({ plugins });
} catch (err) {
const m = /Plugin (.+) not found/.exec(err.message);
if (m) console.error(`Import or register plugin "${m[1]}" before init`);
else throw err;
} Prevention
- Pass imported plugin functions instead of string ids when possible
- If using string ids, register them via grapesjs.plugins.add first
- Pin plugin versions compatible with your GrapesJS major version
- Check for missing script tags/imports in global (UMD) setups
When it happens
Trigger: Listing a plugin id in `grapesjs.init({ plugins: [...] })` that was never registered via `grapesjs.plugins.add(id, plugin)` nor imported and passed as a function; passing a string id whose npm package isn't loaded (e.g. missing import/CDN script).
Common situations: Forgetting to import the plugin module (global vs module builds), wrong plugin name casing, plugin package not installed, loading plugins on the server where the global isn't attached, GrapesJS v4 plugin API changes.
Related errors
- Parser code "${parserCode}" not found
- Target option is required
- Cannot modify immutable record
- Cannot remove immutable record
- 'container' is required
AI-assisted analysis of GrapesJS/grapesjs@2bdeda85b8 (2026-08-30).
Data as JSON: /api/errors/a1b3bbbff70d45d5.
Report an issue: GitHub.