{"record":{"id":"9ee8874980f44b98","repo":"codex-team/editor.js","slug":"holder-value-must-be-an-element-node","errorCode":null,"errorMessage":"«holder» value must be an Element node","messagePattern":"«holder» value must be an Element node","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"src/components/core.ts","lineNumber":218,"sourceCode":"  /**\n   * Checks for required fields in Editor's config\n   */\n  public validate(): void {\n    const { holderId, holder } = this.config;\n\n    if (holderId && holder) {\n      throw Error('«holderId» and «holder» param can\\'t assign at the same time.');\n    }\n\n    /**\n     * Check for a holder element's existence\n     */\n    if (_.isString(holder) && !$.get(holder)) {\n      throw Error(`element with ID «${holder}» is missing. Pass correct holder's ID.`);\n    }\n\n    if (holder && _.isObject(holder) && !$.isElement(holder)) {\n      throw Error('«holder» value must be an Element node');\n    }\n  }\n\n  /**\n   * Initializes modules:\n   *  - make and save instances\n   *  - configure\n   */\n  public init(): void {\n    /**\n     * Make modules instances and save it to the @property this.moduleInstances\n     */\n    this.constructModules();\n\n    /**\n     * Modules configuration\n     */\n    this.configureModules();","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/codex-team/editor.js/blob/5f45dabbe5690b7033b2f9047d3985add5045fdd/src/components/core.ts#L200-L236","documentation":"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.","triggerScenarios":"Passing a jQuery collection like $('.editor') (an object, not an Element), a plain object, or the result of querySelectorAll (a NodeList) as holder.","commonSituations":"Migrating jQuery-era code; passing document.querySelectorAll output instead of [0]; wrapping the node in an extra object during config assembly.","solutions":["Pass the raw DOM element: holder: document.querySelector('#editorjs')","Unwrap jQuery: holder: $('.editor').get(0)","Index NodeList results: holder: nodes[0]"],"exampleFix":"// before\nnew EditorJS({ holder: $('.editor'), tools });\n// after\nnew EditorJS({ holder: $('.editor').get(0), tools });","handlingStrategy":"type-guard","validationCode":"const el = holder instanceof Element ? holder : document.querySelector(String(holder)); new EditorJS({ holder: el ?? document.createElement('div') });","typeGuard":"const isElement = (v: unknown): v is Element => v instanceof Element;","tryCatchPattern":"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; }","preventionTips":["Unwrap jQuery collections with .get(0)","Pass querySelector result, not querySelectorAll"],"tags":["config","holder","dom-element","type-validation"],"backgroundTag":"invalid-argument-type","analyzedSha":"5f45dabbe5690b7033b2f9047d3985add5045fdd","analyzedAt":"2026-08-27T22:50:23.124Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}