{"record":{"id":"fb3a0d98c68ad510","repo":"slab/quill","slug":"cannot-initialize-quill-without-scrollblotname","errorCode":null,"errorMessage":"Cannot initialize Quill without \"${scrollBlotName}\" blot","messagePattern":"Cannot initialize Quill without \"(.+?)\" blot","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"packages/quill/src/core/quill.ts","lineNumber":218,"sourceCode":"    this.container = this.options.container;\n    if (this.container == null) {\n      debug.error('Invalid Quill container', container);\n      return;\n    }\n    if (this.options.debug) {\n      Quill.debug(this.options.debug);\n    }\n    const html = this.container.innerHTML.trim();\n    this.container.classList.add('ql-container');\n    this.container.innerHTML = '';\n    instances.set(this.container, this);\n    this.root = this.addContainer('ql-editor');\n    this.root.classList.add('ql-blank');\n    this.emitter = new Emitter();\n    const scrollBlotName = Parchment.ScrollBlot.blotName;\n    const ScrollBlot = this.options.registry.query(scrollBlotName);\n    if (!ScrollBlot || !('blotName' in ScrollBlot)) {\n      throw new Error(\n        `Cannot initialize Quill without \"${scrollBlotName}\" blot`,\n      );\n    }\n    this.scroll = new ScrollBlot(this.options.registry, this.root, {\n      emitter: this.emitter,\n    }) as Scroll;\n    this.editor = new Editor(this.scroll);\n    this.selection = new Selection(this.scroll, this.emitter);\n    this.composition = new Composition(this.scroll, this.emitter);\n    this.theme = new this.options.theme(this, this.options); // eslint-disable-line new-cap\n    this.keyboard = this.theme.addModule('keyboard');\n    this.clipboard = this.theme.addModule('clipboard');\n    this.history = this.theme.addModule('history');\n    this.uploader = this.theme.addModule('uploader');\n    this.theme.addModule('input');\n    this.theme.addModule('uiNode');\n    this.theme.init();\n    this.emitter.on(Emitter.events.EDITOR_CHANGE, (type) => {","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/slab/quill/blob/539cbffd0a13b18e9c65eb84dd35e6596e403158/packages/quill/src/core/quill.ts#L200-L236","documentation":"Quill builds its editor tree on top of Parchment's root \"scroll\" blot (blotName 'scroll', defined at packages/quill/src/blots/scroll.ts:31). The constructor queries the configured registry for Parchment.ScrollBlot.blotName and throws if the lookup returns nothing or a value without a blotName property. This means the registry in options.registry does not contain Quill's core scroll blot, so the editor cannot be rooted.","triggerScenarios":"Passing a hand-built options.registry (new Registry()) that was never seeded with the scroll blot; running in an SSR/isomorphic context where the parchment global registry side-effects never executed; a custom registry whose query('scroll') was overridden/removed; tree-shaking that dropped quill's core blot registration imports.","commonSituations":"Switching from the formats option to a custom registry to sandbox formats but forgetting core blots; Quill v1->v2 migration where the global registry seeding moved behind an explicit import; bundler misconfiguration stripping side-effectful imports from packages/quill/src/quill.ts.","solutions":["Drop the custom registry and use the formats option instead: createRegistryWithFormats (packages/quill/src/core/utils/createRegistryWithFormats.ts:4) always seeds CORE_FORMATS ['block','break','cursor','inline','scroll','text'], so scroll is guaranteed present.","If you must keep a custom registry, register the scroll blot on it: const Scroll = Quill.import('blots/scroll'); myRegistry.register(Scroll); before passing it as options.registry.","Ensure the full Quill build side effects ran (import Quill from 'quill' rather than cherry-picking submodules) so parchment's global registry is populated.","In SSR, guard construction behind a typeof window check and only instantiate Quill in the browser where registration side effects have executed."],"exampleFix":"// before\nconst registry = new Registry();\nconst quill = new Quill(el, { registry }); // throws: scroll blot missing\n\n// after - use formats so core blots are auto-included\nconst quill = new Quill(el, { formats: ['bold', 'italic', 'list'] });\n\n// or, register scroll on a custom registry\nimport { Quill } from 'quill';\nimport { Registry } from 'parchment';\nconst registry = new Registry();\nregistry.register(Quill.import('blots/scroll'));\nconst quill = new Quill(el, { registry });","handlingStrategy":"validation","validationCode":"// Run before constructing Quill with a custom registry\nimport { Quill } from 'quill';\n\nfunction assertScrollBlotPresent(registry) {\n  const scrollBlotName = registry.constructor.name && 'scroll'; // 'scroll' per packages/quill/src/blots/scroll.ts:32\n  const ScrollBlot = registry.query(scrollBlotName);\n  if (!ScrollBlot || !(typeof ScrollBlot === 'function' && 'blotName' in ScrollBlot)) {\n    throw new Error(\n      `options.registry is missing the \"${scrollBlotName}\" blot; use the formats option or register Quill.import('blots/scroll').`,\n    );\n  }\n}\n\n// usage\nconst registry = options.registry ?? Quill.import('core').globalRegistry;\nassertScrollBlotPresent(registry);\nconst quill = new Quill(el, { ...options, registry });","typeGuard":"// Narrows a registry to one known to contain the scroll blot\nfunction hasScrollBlot(registry) {\n  const blot = registry.query('scroll');\n  return blot != null && typeof blot === 'function' && 'blotName' in blot;\n}\n\n// usage\nif (hasScrollBlot(myRegistry)) {\n  const quill = new Quill(el, { registry: myRegistry });\n}","tryCatchPattern":"try {\n  const quill = new Quill(el, options);\n} catch (err) {\n  if (String(err?.message).includes('Cannot initialize Quill without')) {\n    // registry is missing core blots - fall back to default registry / formats option\n    console.error('Quill init failed: custom registry lacks the scroll blot.', err);\n  }\n  throw err;\n}","preventionTips":["Prefer the formats option over a custom registry; createRegistryWithFormats always seeds CORE_FORMATS including 'scroll'.","If you build a Registry by hand, register Quill.import('blots/scroll') and the other core blots (block, break, cursor, inline, text) before use.","Import the full Quill build (from 'quill') rather than deep submodule paths so registration side effects run.","In SSR, only construct Quill in the browser after registration side effects have executed."],"tags":["registry","parchment","blot","initialization","scroll"],"backgroundTag":null,"analyzedSha":"539cbffd0a13b18e9c65eb84dd35e6596e403158","analyzedAt":"2026-08-12T17:15:45.919Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}