hakimel/reveal.js · critical · Error

Unable to find presentation root (<div class="reveal">).

Error message

Unable to find presentation root (<div class="reveal">).

What it means

Reveal.initialize (js/index.ts:30) bootstraps the singleton deck by querying document.querySelector('.reveal') and requires it to be an HTMLElement. If the selector returns null or a non-element node, initialize throws before constructing the Deck. This is the single hard precondition for bootstrapping reveal.js: the presentation root element must exist in the document at the moment initialize runs.

Source

Thrown at js/index.ts:44

 * reveal.js API and ensures backwards compatibility.
 * This API only allows for one Reveal instance per
 * page, whereas the new API above lets you run many
 * presentations on the same page.
 *
 * Reveal.initialize( { controls: false } ).then(() => {
 *   // reveal.js is ready
 * });
 */

type RevealApiFunction = (deck: RevealApi) => any;

const enqueuedAPICalls: RevealApiFunction[] = [];

Reveal.initialize = (options?: RevealConfig) => {
	const revealElement = document.querySelector('.reveal');

	if (!(revealElement instanceof HTMLElement)) {
		throw new Error('Unable to find presentation root (<div class="reveal">).');
	}

	// Create our singleton reveal.js instance
	Object.assign(Reveal, new Deck(revealElement, options));

	// Invoke any enqueued API calls
	enqueuedAPICalls.map((method) => method(Reveal as RevealApi));

	return Reveal.initialize();
};

/**
 * The pre 4.0 API let you add event listener before
 * initializing. We maintain the same behavior by
 * queuing up premature API calls and invoking all
 * of them when Reveal.initialize is called.
 */
(

View on GitHub (pinned to a3b9406956)

Solutions

  1. Ensure the HTML contains <div class="reveal"> ... </div> and that initialize runs after it is parsed — wrap the call in DOMContentLoaded or place the script with defer at the end of <body>.
  2. Verify the element exists before initializing: const el = document.querySelector('.reveal'); if (el) Reveal.initialize(opts).
  3. Double-check the class spelling and that no build step strips class attributes from the root.
  4. If integrating under React/Vue/etc., defer Reveal.initialize to a post-mount effect where the root node is guaranteed present.

Example fix

// before (runs during module eval, DOM not ready)
import Reveal from 'reveal.js';
Reveal.initialize({ controls: true });

// after
import Reveal from 'reveal.js';
document.addEventListener('DOMContentLoaded', () => {
  Reveal.initialize({ controls: true });
});
Defensive patterns

Strategy: validation

Validate before calling

function initializeWhenReady(options) {
  const start = () => {
    const root = document.querySelector('.reveal');
    if (!(root instanceof HTMLElement)) {
      console.error('Reveal: no <div class="reveal"> found in the document.');
      return;
    }
    Reveal.initialize(options);
  };
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', start, { once: true });
  } else {
    start();
  }
}

Type guard

function hasRevealRoot(doc = document) {
  return doc.querySelector('.reveal') instanceof HTMLElement;
}

Try / catch

try {
  Reveal.initialize(options);
} catch (e) {
  if (/presentation root/.test(e.message)) {
    document.addEventListener('DOMContentLoaded', () => Reveal.initialize(options), { once: true });
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Calling Reveal.initialize before the DOM is parsed (script in <head> without defer, or a module that runs during SSR where document has no .reveal); the root <div> missing the class attribute 'reveal'; the class mistyped (e.g. 'reveals', 'reveal.js'); a custom mount where the root was renamed; running initialize twice after the element was removed.

Common situations: Bundlers that execute the initialize call at import time instead of after DOMContentLoaded; embedding reveal.js into another framework's mount lifecycle that has not yet rendered the root; copy-paste setups that dropped the wrapper <div class="reveal">; ES module import order placing initialize ahead of the HTML.


AI-assisted analysis of hakimel/reveal.js@a3b9406956 (2026-08-12). Data as JSON: /api/errors/a16be0e6fc98722b. Report an issue: GitHub.