dotnet/AspNetCore.Docs · error · Error

${this.type} `template` option must consist of exactly 1 top

Error message

${this.type} `template` option must consist of exactly 1 top-level element!

What it means

Identical guard to error 0 in the 3.x sample copy of bootstrap.js: Tooltip.prototype.tip() requires the `template` option to yield exactly one top-level element via $(). `${this.type}` is "tooltip" or "popover".

Source

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

      var o  = this.options
  
      title = $e.attr('data-original-title')
        || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
  
      return title
    }
  
    Tooltip.prototype.getUID = function (prefix) {
      do prefix += ~~(Math.random() * 1000000)
      while (document.getElementById(prefix))
      return prefix
    }
  
    Tooltip.prototype.tip = function () {
      if (!this.$tip) {
        this.$tip = $(this.options.template)
        if (this.$tip.length != 1) {
          throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
        }
      }
      return this.$tip
    }
  
    Tooltip.prototype.arrow = function () {
      return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
    }
  
    Tooltip.prototype.enable = function () {
      this.enabled = true
    }
  
    Tooltip.prototype.disable = function () {
      this.enabled = false
    }
  
    Tooltip.prototype.toggleEnabled = function () {

View on GitHub (pinned to c67a80103a)

Solutions

  1. Use a single rooted HTML element string for template.
  2. Don't pass selectors as templates.
  3. Drop the template option to fall back to Bootstrap's default.

Example fix

// before
$('#el').tooltip({ template: '' });
// after
$('#el').tooltip({ template: '<div class="tooltip" role="tooltip"><div class="tooltip-inner"></div></div>' });
Defensive patterns

Strategy: validation

Validate before calling

function isValidTooltipTemplate(tpl) {
  if (typeof tpl !== 'string' || tpl.trim() === '') return false;
  var nodes = $(tpl);
  return nodes.length === 1 && nodes[0].nodeType === 1;
}
if (options.template && !isValidTooltipTemplate(options.template)) {
  console.warn('Invalid tooltip template; using default');
  delete options.template;
}
$('#el').tooltip(options);

Type guard

function isSingleElementTemplate(tpl) { return typeof tpl === 'string' && $(tpl).length === 1; }

Try / catch

try {
  $('#el').tooltip({ template: customTpl });
} catch (e) {
  if (/template.*1 top-level element/.test(e.message)) {
    $('#el').tooltip({});
  } else { throw e; }
}

Prevention

When it happens

Trigger: Passing a template with 0 or 2+ top-level nodes, a CSS selector instead of HTML, or an empty string to .tooltip({template})/.popover({template}) in the 3.x sample app.

Common situations: Customizing tooltip markup; cross-version template copy; bundler string corruption.

Related errors


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