jsdom/jsdom · error · TypeError
The options object must set at least one of 'attributes', 'c
Error message
The options object must set at least one of 'attributes', 'characterData', or 'childList' to true.
What it means
MutationObserver.observe() requires the options dict to request at least one observation type. jsdom validates options before registering the observer and throws this TypeError when `childList`, `attributes`, and `characterData` are all falsy, meaning the observer would never deliver any record.
Source
Thrown at lib/jsdom/living/mutation-observer/MutationObserver-impl.js:38
this._callback = callback;
this._nodeList = new IterableWeakList();
this._recordQueue = [];
this._id = ++mutationObserverId;
}
// https://dom.spec.whatwg.org/#dom-mutationobserver-observe
observe(target, options) {
if (("attributeOldValue" in options || "attributeFilter" in options) && !("attributes" in options)) {
options.attributes = true;
}
if ("characterDataOldValue" in options & !("characterData" in options)) {
options.characterData = true;
}
if (!options.childList && !options.attributes && !options.characterData) {
throw new TypeError("The options object must set at least one of 'attributes', 'characterData', or 'childList' " +
"to true.");
} else if (options.attributeOldValue && !options.attributes) {
throw new TypeError("The options object may only set 'attributeOldValue' to true when 'attributes' is true or " +
"not present.");
} else if (("attributeFilter" in options) && !options.attributes) {
throw new TypeError("The options object may only set 'attributeFilter' when 'attributes' is true or not " +
"present.");
} else if (options.characterDataOldValue && !options.characterData) {
throw new TypeError("The options object may only set 'characterDataOldValue' to true when 'characterData' is " +
"true or not present.");
}
const existingRegisteredObserver = target._registeredObserverList.find(registeredObserver => {
return registeredObserver.observer === this;
});
if (existingRegisteredObserver) {
for (const node of this._nodeList) {View on GitHub (pinned to 904cc9cd24)
Solutions
- Set at least one observation flag to true: `{ childList: true }`, `{ attributes: true }`, or `{ characterData: true }`.
- Log the options object right before observe() to confirm actual key names and boolean values.
- Fix any string-to-boolean conversion so values are real booleans, not 'true'/'false' strings.
- Default missing flags at call sites: `const opts = { childList: true, ...options };` only if intentional.
Example fix
// before
observer.observe(target, {}); // TypeError
// after
observer.observe(target, { childList: true, subtree: true }); Defensive patterns
Strategy: validation
Validate before calling
function validObserveOptions(o = {}) {
return Boolean(o.childList) || Boolean(o.attributes) || Boolean(o.characterData);
}
if (!validObserveOptions(options)) throw new TypeError('observe options must enable childList, attributes, or characterData'); Type guard
function hasObservationFlag(o) {
return o != null && ['childList', 'attributes', 'characterData'].some(k => o[k] === true);
} Try / catch
try {
observer.observe(target, options);
} catch (e) {
if (e instanceof TypeError && /at least one of/.test(e.message)) {
observer.observe(target, { ...options, childList: true });
} else {
throw e;
}
} Prevention
- Always pass at least one of childList/attributes/characterData as a real boolean.
- Coerce config values with Boolean() to avoid 'false' strings being truthy or flags being falsy.
- Unit-test the options object your app builds for observe().
When it happens
Trigger: `observer.observe(target, {})`; passing options whose values are the strings 'false'/'undefined' or 0 rather than booleans; building options dynamically and ending with all three keys false or absent.
Common situations: Serializing options from config/JSON where booleans became strings; spreading a partial options object that omits all three keys; refactoring that renamed a key (e.g. `child` instead of `childList`).
Related errors
- The options object may only set 'attributeOldValue' to true
- The options object may only set 'attributeFilter' when 'attr
- The options object may only set 'characterDataOldValue' to t
- Invalid Sequence
- Constructor argument is not a constructor.
AI-assisted analysis of jsdom/jsdom@904cc9cd24 (2026-09-01).
Data as JSON: /api/errors/749c37d2bdd0b938.
Report an issue: GitHub.