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
- Pass the raw DOM element: holder: document.querySelector('#editorjs')
- Unwrap jQuery: holder: $('.editor').get(0)
- 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
- Unwrap jQuery collections with .get(0)
- Pass querySelector result, not querySelectorAll
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
- «holderId» and «holder» param can't assign at the same time.
- element with ID «${holder}» is missing. Pass correct holder'
- Index should be a number
AI-assisted analysis of codex-team/editor.js@5f45dabbe5 (2026-08-27).
Data as JSON: /api/errors/9ee8874980f44b98.
Report an issue: GitHub.