HandyOrg/HandyControl · warning

Tabs block must have unique name!

Error message

Tabs block must have unique name!

What it means

The NexT theme's tabs Hexo tag warns when the tabs block name (the first argument or the Unique name after '@') is missing. The warning is non-fatal — tabId falls back to 0 and rendering continues — but duplicate or missing names can break tab switching and anchor uniqueness across the page.

Solutions

  1. Add a unique name as the first argument: {% tabs Unique name %}.
  2. Give every tabs block on the page a distinct name to avoid duplicate ids.
  3. Optionally pass a pre-selected tab index as the second argument ({% tabs name, 1 %}).

Example fix

// before
{% tabs %}
<!-- tab -->
content
{% endtabs %}
// after
{% tabs Demo Tab %}
<!-- tab -->
content
{% endtabs %}
Defensive patterns

Strategy: validation

Validate before calling

function checkTabsArgs(rawArgs) {
  const name = rawArgs.join(' ').split(',')[0].trim();
  if (!name) {
    console.warn('{% tabs %} requires a unique name: {% tabs Unique name %}');
    return false;
  }
  return true;
}

Type guard

function hasTabName(args) {
  const name = args.join(' ').split(',')[0];
  return typeof name === 'string' && name.trim().length > 0;
}

Prevention

When it happens

Trigger: Using {% tabs %} ... {% endtabs %} with no name argument, so tabName is empty; the tag expects {% tabs Unique name %} or {% tabs name, index %}.

Common situations: Authors copying the closing {% endtabs %} correctly but forgetting the name after {% tabs %}, or using tabs blocks with identical names on one page causing id collisions.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of HandyOrg/HandyControl@2c0875ebd6 (2026-09-14). Data as JSON: /api/errors/d7d7e47c4785b51f. Report an issue: GitHub.

Appendix: source

Thrown at doc/themes/next/scripts/tags/tabs.js:22

/* global hexo */

'use strict';

function postTabs(args, content) {
  var tabBlock = /<!--\s*tab (.*?)\s*-->\n([\w\W\s\S]*?)<!--\s*endtab\s*-->/g;

  args = args.join(' ').split(',');
  var tabName = args[0];
  var tabActive = Number(args[1]) || 0;

  var matches = [];
  var match;
  var tabId = 0;
  var tabNav = '';
  var tabContent = '';

  !tabName && hexo.log.warn('Tabs block must have unique name!');

  while ((match = tabBlock.exec(content)) !== null) {
    matches.push(match[1]);
    matches.push(match[2]);
  }

  for (var i = 0; i < matches.length; i += 2) {
    var tabParameters = matches[i].split('@');
    var postContent   = matches[i + 1];
    var tabCaption    = tabParameters[0] || '';
    var tabIcon       = tabParameters[1] || '';
    var tabHref       = '';

    postContent = hexo.render.renderSync({text: postContent, engine: 'markdown'}).trim();

    tabId += 1;
    tabHref = (tabName + ' ' + tabId).toLowerCase().split(' ').join('-');

View on GitHub (pinned to 2c0875ebd6)