usablica/intro.js · error
Element with selector ${selector} not found
Error message
Element with selector ${selector} not found What it means
getElement() resolves a CSS selector via queryElement() and throws when nothing matches in the document (or the optional container). Unlike queryElement(), which returns null, getElement() is the strict variant asserting the element must exist, used to initialize tours/hints against required DOM nodes.
Source
Thrown at src/util/queryElement.ts:29
): NodeListOf<HTMLElement> => {
return (container ?? document).querySelectorAll(selector);
};
export const queryElementsByClassName = (
className: string,
container?: HTMLElement | null
): NodeListOf<HTMLElement> => {
return queryElements(`.${className}`, container);
};
export const getElement = (
selector: string,
container?: HTMLElement | null
) => {
const element = queryElement(selector, container);
if (!element) {
throw new Error(`Element with selector ${selector} not found`);
}
return element;
};
View on GitHub (pinned to e5517e6a24)
Solutions
- Call the tour/hint setup after the DOM element exists (on mount / DOMContentLoaded / after render).
- Verify the selector matches in DevTools (document.querySelector(selector) !== null) — check for missing '.', '#', typos.
- Pass the correct container argument if the element lives inside a specific container.
- If the element is optional, use queryElement() (returns null) instead of getElement().
Example fix
// before
introJs.tour('#save-button'); // may run before render
// after
document.addEventListener('DOMContentLoaded', () => {
if (document.querySelector('#save-button')) introJs.tour('#save-button');
}); Defensive patterns
Strategy: validation
Validate before calling
const el = document.querySelector('#save-button');
if (!el) throw new Error('#save-button missing — aborting tour setup');
introJs.tour('#save-button'); Type guard
function elementExists(selector: string, root: ParentNode = document): boolean {
return root.querySelector(selector) !== null;
} Try / catch
try {
introJs.tour('#save-button');
} catch (e) {
if (String(e.message).includes('not found')) {
console.warn('Tour target missing, skipping intro:', e.message);
} else throw e;
} Prevention
- Initialize tours after DOM render (DOMContentLoaded, framework mount hooks).
- Validate selectors with document.querySelector before registering.
- Double-check '#'/ '.' prefixes and spelling of ids/classes.
- For optional elements, use queryElement() which returns null instead of throwing.
- In SPAs, re-run setup when route/dynamic content changes.
When it happens
Trigger: Calling introJs.tour('#step-1') or any API that runs getElement() with a selector that matches no element, a misspelled selector, an element inside a container passed as null, or an element not yet rendered when the call executes.
Common situations: Calling intro before the DOM has rendered (scripts in <head>, SPA route mount race, dynamic content not yet injected); typo in class/id (missing dot or hash); element only exists conditionally; SSR where document has no such element; scoping to a container that doesn't contain the node.
AI-assisted analysis of usablica/intro.js@e5517e6a24 (2026-08-31).
Data as JSON: /api/errors/79f33b1634ca8a31.
Report an issue: GitHub.