{"record":{"id":"749c37d2bdd0b938","repo":"jsdom/jsdom","slug":"the-options-object-must-set-at-least-one-of-attri","errorCode":null,"errorMessage":"The options object must set at least one of 'attributes', 'characterData', or 'childList' to true.","messagePattern":"The options object must set at least one of 'attributes', 'characterData', or 'childList' to true\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"lib/jsdom/living/mutation-observer/MutationObserver-impl.js","lineNumber":38,"sourceCode":"    this._callback = callback;\n    this._nodeList = new IterableWeakList();\n    this._recordQueue = [];\n\n    this._id = ++mutationObserverId;\n  }\n\n  // https://dom.spec.whatwg.org/#dom-mutationobserver-observe\n  observe(target, options) {\n    if ((\"attributeOldValue\" in options || \"attributeFilter\" in options) && !(\"attributes\" in options)) {\n      options.attributes = true;\n    }\n\n    if (\"characterDataOldValue\" in options & !(\"characterData\" in options)) {\n      options.characterData = true;\n    }\n\n    if (!options.childList && !options.attributes && !options.characterData) {\n      throw new TypeError(\"The options object must set at least one of 'attributes', 'characterData', or 'childList' \" +\n        \"to true.\");\n    } else if (options.attributeOldValue && !options.attributes) {\n      throw new TypeError(\"The options object may only set 'attributeOldValue' to true when 'attributes' is true or \" +\n        \"not present.\");\n    } else if ((\"attributeFilter\" in options) && !options.attributes) {\n      throw new TypeError(\"The options object may only set 'attributeFilter' when 'attributes' is true or not \" +\n        \"present.\");\n    } else if (options.characterDataOldValue && !options.characterData) {\n      throw new TypeError(\"The options object may only set 'characterDataOldValue' to true when 'characterData' is \" +\n        \"true or not present.\");\n    }\n\n    const existingRegisteredObserver = target._registeredObserverList.find(registeredObserver => {\n      return registeredObserver.observer === this;\n    });\n\n    if (existingRegisteredObserver) {\n      for (const node of this._nodeList) {","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/jsdom/jsdom/blob/904cc9cd2464e959b739910cb046afe57f7a1922/lib/jsdom/living/mutation-observer/MutationObserver-impl.js#L20-L56","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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`).","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."],"exampleFix":"// before\nobserver.observe(target, {}); // TypeError\n\n// after\nobserver.observe(target, { childList: true, subtree: true });","handlingStrategy":"validation","validationCode":"function validObserveOptions(o = {}) {\n  return Boolean(o.childList) || Boolean(o.attributes) || Boolean(o.characterData);\n}\nif (!validObserveOptions(options)) throw new TypeError('observe options must enable childList, attributes, or characterData');","typeGuard":"function hasObservationFlag(o) {\n  return o != null && ['childList', 'attributes', 'characterData'].some(k => o[k] === true);\n}","tryCatchPattern":"try {\n  observer.observe(target, options);\n} catch (e) {\n  if (e instanceof TypeError && /at least one of/.test(e.message)) {\n    observer.observe(target, { ...options, childList: true });\n  } else {\n    throw e;\n  }\n}","preventionTips":["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()."],"tags":["mutation-observer","typeerror","options-validation"],"backgroundTag":"invalid-mutation-observer-options","analyzedSha":"904cc9cd2464e959b739910cb046afe57f7a1922","analyzedAt":"2026-09-01T11:17:47.630Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}