twbs/bootstrap · error · TypeError

${NAME.toUpperCase()}: Option "reference" provided type "obj

Error message

${NAME.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.

What it means

Dropdown positions its menu with Popper, and the 'reference' option accepts 'toggle' (default), 'parent', a DOM element, or a Popper virtual element. _getConfig (dropdown.js:212) rejects objects that are neither elements nor expose a getBoundingClientRect method, because Popper needs that method to compute the menu position. The check runs on every Dropdown construction, including data-bs-toggle clicks that carry a programmatic config.

Source

Thrown at js/src/dropdown.js:219

    if (this._popper) {
      this._popper.destroy()
    }

    this._menu.classList.remove(CLASS_NAME_SHOW)
    this._element.classList.remove(CLASS_NAME_SHOW)
    this._element.setAttribute('aria-expanded', 'false')
    Manipulator.removeDataAttribute(this._menu, 'popper')
    EventHandler.trigger(this._element, EVENT_HIDDEN, relatedTarget)
  }

  _getConfig(config) {
    config = super._getConfig(config)

    if (typeof config.reference === 'object' && !isElement(config.reference) &&
      typeof config.reference.getBoundingClientRect !== 'function'
    ) {
      // Popper virtual elements require a getBoundingClientRect method
      throw new TypeError(`${NAME.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`)
    }

    return config
  }

  _createPopper() {
    if (typeof Popper === 'undefined') {
      throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org/docs/v2/)')
    }

    let referenceElement = this._element

    if (this._config.reference === 'parent') {
      referenceElement = this._parent
    } else if (isElement(this._config.reference)) {
      referenceElement = getElement(this._config.reference)
    } else if (typeof this._config.reference === 'object') {
      referenceElement = this._config.reference

View on GitHub (pinned to 6177d5f849)

Solutions

  1. Pass a real DOM element: document.querySelector('#ref') or $('.ref')[0].
  2. Unwrap framework refs — React: ref.current, Vue 3: ref.value.
  3. For a virtual anchor, provide the required method: { getBoundingClientRect: () => target.getBoundingClientRect() }.
  4. When the reference is the adjacent parent, just use reference: 'parent'.

Example fix

// before
new bootstrap.Dropdown(btn, { reference: $('#menuRef') })
// DROPDOWN: Option "reference" provided type "object" without a required "getBoundingClientRect" method.

// after — DOM element
new bootstrap.Dropdown(btn, { reference: document.querySelector('#menuRef') })

// after — Popper virtual element
new bootstrap.Dropdown(btn, {
  reference: { getBoundingClientRect: () => anchorEl.getBoundingClientRect() }
})
Defensive patterns

Strategy: validation

Validate before calling

function isDropdownReference(ref) {
  if (typeof ref === 'string') return ref === 'toggle' || ref === 'parent'
  if (ref instanceof Element) return true
  return typeof ref?.getBoundingClientRect === 'function' // Popper virtual element
}

if (!isDropdownReference(options.reference)) {
  throw new TypeError('reference must be "toggle"|"parent", a DOM element, or a virtual element with getBoundingClientRect')
}
new bootstrap.Dropdown(btn, options)

Type guard

function isVirtualElement(ref: unknown): ref is { getBoundingClientRect: () => DOMRect } {
  return typeof ref === 'object' && ref !== null &&
    !(ref instanceof Element) &&
    typeof (ref as { getBoundingClientRect?: unknown }).getBoundingClientRect === 'function'
}

Try / catch

try {
  new bootstrap.Dropdown(btn, options)
} catch (err) {
  if (err instanceof TypeError && /Option "reference"/.test(err.message)) {
    // fall back to the default reference ('toggle') and log the bad value's shape
    new bootstrap.Dropdown(btn)
  } else {
    throw err
  }
}

Prevention

When it happens

Trigger: new bootstrap.Dropdown(btn, { reference: $('.ref') }) — a jQuery collection is a plain object without getBoundingClientRect; { reference: { top: 0, left: 0 } }; { reference: window } or document; passing a React ref object ({ current: el }) or Vue template ref instead of ref.current / ref.value.

Common situations: jQuery-era code passing collections instead of single elements; framework wrappers (React/Vue) leaking ref objects into config; building custom virtual anchors for dropdowns attached to canvas, SVG or table cells; mixing up the 'parent' string with an object.

Related errors


AI-assisted analysis of twbs/bootstrap@6177d5f849 (2026-08-22). Data as JSON: /api/errors/825a672e4a51ad64. Report an issue: GitHub.