dotnet/AspNetCore.Docs · error · Error

`selector` option must be specified when initializing ${this

Error message

`selector` option must be specified when initializing ${this.type} on the window.document object!

What it means

Bootstrap's Tooltip.init detects when the bound element is the document object itself (this.$element[0] instanceof document.constructor). Binding a tooltip/popover directly to document only makes sense as delegated initialization, which requires the `selector` option to tell Bootstrap which descendant elements actually carry the tooltip. Without `selector`, Bootstrap refuses — silently binding a single tooltip to document would never trigger correctly.

Source

Thrown at aspnetcore/mvc/controllers/testing/samples/3.x/TestingControllersSample/src/TestingControllersSample/wwwroot/js/bootstrap.js:1314

      delay: 0,
      html: false,
      container: false,
      viewport: {
        selector: 'body',
        padding: 0
      }
    }
  
    Tooltip.prototype.init = function (type, element, options) {
      this.enabled   = true
      this.type      = type
      this.$element  = $(element)
      this.options   = this.getOptions(options)
      this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
      this.inState   = { click: false, hover: false, focus: false }
  
      if (this.$element[0] instanceof document.constructor && !this.options.selector) {
        throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
      }
  
      var triggers = this.options.trigger.split(' ')
  
      for (var i = triggers.length; i--;) {
        var trigger = triggers[i]
  
        if (trigger == 'click') {
          this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
        } else if (trigger != 'manual') {
          var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
          var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
  
          this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
          this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
        }
      }
  

View on GitHub (pinned to c67a80103a)

Solutions

  1. Add a selector option: $(document).tooltip({ selector: '[data-toggle="tooltip"]' });
  2. Prefer binding delegation to a closer container than document (e.g. $('body')) for performance.
  3. If you didn't mean delegation, bind to the actual elements: $('[data-toggle="tooltip"]').tooltip().

Example fix

// before
$(document).tooltip({ placement: 'top' }); // throws
// after (delegated)
$(document).tooltip({ selector: '[data-toggle="tooltip"]', placement: 'top' });
// or (direct)
$('[data-toggle="tooltip"]').tooltip({ placement: 'top' });
Defensive patterns

Strategy: validation

Validate before calling

// Ensure a selector is supplied when delegating from document/body.
function delegatedTooltip($host, opts) {
  if (($host[0] === document || $host[0] === document.body) && !(opts && opts.selector)) {
    throw new Error('Delegated tooltip on document requires opts.selector');
  }
  $host.tooltip(opts);
}
delegatedTooltip($(document), { selector: '[data-toggle="tooltip"]' });

Type guard

function isDelegationHost(el) { return el === document || el === document.body; }

Try / catch

try {
  $(document).tooltip(opts);
} catch (e) {
  if (/`selector` option must be specified/.test(e.message)) {
    console.error('Add selector for delegated tooltip init');
    $(document).tooltip(Object.assign({ selector: '[data-toggle="tooltip"]' }, opts));
  } else { throw e; }
}

Prevention

When it happens

Trigger: $(document).tooltip({...}) or $(document).popover({...}) without a `selector` option; copy-pasting element-bound tooltip config onto document for global delegation.

Common situations: Trying to enable tooltips on dynamically injected HTML; converting per-element calls into one delegated call; misunderstanding Bootstrap's delegation API.

Related errors


AI-assisted analysis of dotnet/AspNetCore.Docs@c67a80103a (2026-08-13). Data as JSON: /api/errors/730d81e5ee4c55c6. Report an issue: GitHub.