{"record":{"id":"66a987de24408a08","repo":"slab/quill","slug":"invalid-quill-container","errorCode":null,"errorMessage":"Invalid Quill container","messagePattern":"Invalid Quill container","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"packages/quill/src/core/quill.ts","lineNumber":799,"sourceCode":"      [key]: value === true ? {} : value,\n    }),\n    {} as Record<string, unknown>,\n  );\n}\n\nfunction omitUndefinedValuesFromOptions(obj: QuillOptions) {\n  return Object.fromEntries(\n    Object.entries(obj).filter((entry) => entry[1] !== undefined),\n  );\n}\n\nfunction expandConfig(\n  containerOrSelector: HTMLElement | string,\n  options: QuillOptions,\n): ExpandedQuillOptions {\n  const container = resolveSelector(containerOrSelector);\n  if (!container) {\n    throw new Error('Invalid Quill container');\n  }\n\n  const shouldUseDefaultTheme =\n    !options.theme || options.theme === Quill.DEFAULTS.theme;\n  const theme = shouldUseDefaultTheme\n    ? Theme\n    : Quill.import(`themes/${options.theme}`);\n  if (!theme) {\n    throw new Error(`Invalid theme ${options.theme}. Did you register it?`);\n  }\n\n  const { modules: quillModuleDefaults, ...quillDefaults } = Quill.DEFAULTS;\n  const { modules: themeModuleDefaults, ...themeDefaults } = theme.DEFAULTS;\n\n  let userModuleOptions = expandModuleConfig(options.modules);\n  // Special case toolbar shorthand\n  if (\n    userModuleOptions != null &&","sourceCodeStart":781,"sourceCodeEnd":817,"githubUrl":"https://github.com/slab/quill/blob/539cbffd0a13b18e9c65eb84dd35e6596e403158/packages/quill/src/core/quill.ts#L781-L817","documentation":"expandConfig (packages/quill/src/core/quill.ts:793) calls resolveSelector on the container argument; resolveSelector runs document.querySelector for a string and returns the element directly otherwise. If the result is falsy it throws 'Invalid Quill container'. Quill needs a real, mounted DOM node to attach to before any editor wiring can run.","triggerScenarios":"Passing a CSS selector string that matches no element; calling new Quill('#editor') before the element is in the DOM (script in head without defer, or running before DOMContentLoaded); passing a detached/removed HTMLElement; running where document is absent (SSR) so querySelector returns null.","commonSituations":"Script tag in <head> executing before the body is parsed; SPA frameworks instantiating Quill in created() instead of mounted()/onMounted(); selector typo or renamed element id; hydration races where the container is conditionally rendered.","solutions":["Defer initialization until the element exists: run new Quill inside DOMContentLoaded, or in the framework's onMounted/afterViewInit/componentDidMount lifecycle hook.","Pass the element reference directly instead of a selector string: new Quill(document.getElementById('editor')) to remove querySelector ambiguity.","Verify the selector resolves before constructing: if (!document.querySelector(sel)) return;.","In an SPA, ensure the container is rendered (v-if resolved) before the Quill initialization effect runs."],"exampleFix":"// before - runs before #editor is in the DOM\nnew Quill('#editor'); // throws: Invalid Quill container\n\n// after - resolve and guard, then pass the element\nconst el = document.querySelector('#editor');\nif (!el) throw new Error('#editor not found');\nnew Quill(el, { theme: 'snow' });\n\n// or, in Vue/React, inside onMounted / useEffect where the ref is set","handlingStrategy":"validation","validationCode":"// Resolve the container yourself before constructing Quill\nfunction resolveQuillContainer(target) {\n  const el =\n    typeof target === 'string'\n      ? document.querySelector(target)\n      : target;\n  if (!el || !(el instanceof HTMLElement)) {\n    throw new Error(\n      `Invalid Quill container: ${typeof target === 'string' ? target : 'provided element'} is not a mounted HTMLElement`,\n    );\n  }\n  return el;\n}\n\n// usage\nconst el = resolveQuillContainer('#editor');\nnew Quill(el, { theme: 'snow' });","typeGuard":"function isMountedHTMLElement(value) {\n  return value instanceof HTMLElement && document.body.contains(value);\n}\n\n// usage\nconst el = document.querySelector('#editor');\nif (isMountedHTMLElement(el)) {\n  new Quill(el);\n}","tryCatchPattern":null,"preventionTips":["Initialize Quill inside the framework's post-mount lifecycle (onMounted/useEffect/afterViewInit), not in created/setup.","Pass the resolved HTMLElement directly rather than a selector string to eliminate querySelector ambiguity.","For script-tag usage, place the script at the end of <body> or defer it until DOMContentLoaded.","In SPAs with conditional rendering, confirm the container ref is populated before the init effect runs."],"tags":["dom","container","selector","initialization","lifecycle"],"backgroundTag":null,"analyzedSha":"539cbffd0a13b18e9c65eb84dd35e6596e403158","analyzedAt":"2026-08-12T17:15:45.919Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}