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

  1. Import the plugin and pass the function directly: `plugins: [myPlugin]` or `plugins: [[myPlugin, opts]]`.
  2. Register by id first: `grapesjs.plugins.add('my-plugin', myPlugin)` then use the string id.
  3. Verify the plugin package is installed/imported and the id spelling matches exactly.
  4. 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

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


AI-assisted analysis of GrapesJS/grapesjs@2bdeda85b8 (2026-08-30). Data as JSON: /api/errors/a1b3bbbff70d45d5. Report an issue: GitHub.