codex-team/editor.js · critical · Error

«holder» value must be an Element node

Error message

«holder» value must be an Element node

What it means

If `holder` is an object but not a DOM Element (e.g. a jQuery wrapper, a plain config object, a text node, or a window object), config validation throws because the editor requires a genuine Element node to mount into.

Source

Thrown at src/components/core.ts:218

  /**
   * Checks for required fields in Editor's config
   */
  public validate(): void {
    const { holderId, holder } = this.config;

    if (holderId && holder) {
      throw Error('«holderId» and «holder» param can\'t assign at the same time.');
    }

    /**
     * Check for a holder element's existence
     */
    if (_.isString(holder) && !$.get(holder)) {
      throw Error(`element with ID «${holder}» is missing. Pass correct holder's ID.`);
    }

    if (holder && _.isObject(holder) && !$.isElement(holder)) {
      throw Error('«holder» value must be an Element node');
    }
  }

  /**
   * Initializes modules:
   *  - make and save instances
   *  - configure
   */
  public init(): void {
    /**
     * Make modules instances and save it to the @property this.moduleInstances
     */
    this.constructModules();

    /**
     * Modules configuration
     */
    this.configureModules();

View on GitHub (pinned to 5f45dabbe5)

Solutions

  1. Pass the raw DOM element: holder: document.querySelector('#editorjs')
  2. Unwrap jQuery: holder: $('.editor').get(0)
  3. Index NodeList results: holder: nodes[0]

Example fix

// before
new EditorJS({ holder: $('.editor'), tools });
// after
new EditorJS({ holder: $('.editor').get(0), tools });
Defensive patterns

Strategy: type-guard

Validate before calling

const el = holder instanceof Element ? holder : document.querySelector(String(holder)); new EditorJS({ holder: el ?? document.createElement('div') });

Type guard

const isElement = (v: unknown): v is Element => v instanceof Element;

Try / catch

try { new EditorJS({ holder }); } catch (e) { if (e instanceof Error && e.message.includes('must be an Element node')) { new EditorJS({ holder: (holder as any).get?.(0) ?? holder[0] }); return; } throw e; }

Prevention

When it happens

Trigger: Passing a jQuery collection like $('.editor') (an object, not an Element), a plain object, or the result of querySelectorAll (a NodeList) as holder.

Common situations: Migrating jQuery-era code; passing document.querySelectorAll output instead of [0]; wrapping the node in an extra object during config assembly.

Understand the failure class

Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.

Related errors


AI-assisted analysis of codex-team/editor.js@5f45dabbe5 (2026-08-27). Data as JSON: /api/errors/9ee8874980f44b98. Report an issue: GitHub.