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

Bootstrap 3's `Tooltip.tip()` wraps the `template` option in jQuery and throws if the result has `length != 1`. A tooltip/popover needs exactly one root element to position; zero (empty/invalid markup) or multiple roots are rejected.

Source

Thrown at aspnetcore/mvc/views/tag-helpers/th-components/samples/RazorPagesSample/wwwroot/lib/bootstrap/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. Wrap the template in a single root element matching the expected structure: `<div class="tooltip" role="tooltip">...</div>`.
  2. Use the Bootstrap default template as a base and only edit inner HTML.
  3. Validate the template parses to one element before passing it: a quick check with `$(tpl).length === 1`.

Example fix

// before
template: '<div class="tooltip-arrow"></div><div class="tooltip-inner"></div>'

// after
template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
Defensive patterns

Strategy: validation

Validate before calling

function makeTooltip($elem, template) {
  if ($(template).length !== 1) {
    throw new Error('Tooltip template must have exactly one root element');
  }
  $elem.tooltip({ template: template });
}

Type guard

function isSingleRootTemplate(template) {
  return $(template).length === 1;
}

Try / catch

try {
  $el.tooltip({ template: tpl });
} catch (e) {
  if (/template/.test(e.message)) {
    $el.tooltip(); // fall back to default template
  } else throw e;
}

Prevention

When it happens

Trigger: Setting a custom `template` option whose HTML has no top-level element (e.g. plain text) or more than one top-level element (e.g. two sibling divs). The check fires the first time the tooltip element is created.

Common situations: Custom template missing the outer wrapper div; template string has leading text nodes before the root; copy-paste from a partial template that was split across lines; malformed HTML that jQuery parses into multiple fragments.

Related errors


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