amark/gun · error · Error

tag "${name}" is missing hierarchy definition

Error message

tag "${name}" is missing hierarchy definition

What it means

prepareOptTags validates custom options passed to $.normalize: every key in opt.tags must also appear in opt.hierarchy. The hierarchy array defines the canonical tag ordering/structure; a tag present in the tags map but absent from the hierarchy has no defined place in the normalization model, so the library refuses to proceed with this error.

Source

Thrown at lib/normalize.js:101

  }

  function stateMachine() {
    if(unstableList.length===0)
      return;
    var a, i = -1;
    while (a = unstableList.pop()) { // PERF: running index is probably faster than shift (mutates array)
      a.unstable = false;
      $(a.opt.mutate).each(function(i,fn){
        return fn && fn(a, addUnstable);
      });
    }
  }

  function prepareOptTags(opt) {
    var name, tag, tags = opt.tags;
    for(name in tags) {
      if(opt.hierarchy.indexOf(name)===-1)
        throw Error('tag "'+name+'" is missing hierarchy definition');
    }
    opt.hierarchy.forEach(function(name){
      if(!tags[name]){
        tags[name] = {attrs: opt.attrs};
      }
      (tag=tags[name]).attrs = $.extend(tag.attrs||{}, opt.attrs);
      tag.name = name; // not used, debug help (REMOVE later?)
      // order
      tag.order = opt.hierarchy.indexOf(name)
      if(tag.order === -1) {
      throw Error("Order of '"+name+"' not defined in hierarchy");
    }
    });
    return opt;
  }

  // GENERAL UTILS

View on GitHub (pinned to 552227599d)

Solutions

  1. Add every tag listed in opt.tags to the opt.hierarchy array, in the desired structural order.
  2. If the tag needs no special config, add it to hierarchy and let prepareOptTags auto-create tags[name] from opt.attrs.
  3. Fix typos so the tags key exactly matches a hierarchy entry.
  4. Merge from baseOpt so the default hierarchy (div, pre, ol, ul, li, h1-h6, p, a, b, code, i, span, s, sub, sup, u, br, img) is preserved and extend, not replace, it.
  5. Validate customOpt before passing: iterate Object.keys(opt.tags) and assert each is in opt.hierarchy.

Example fix

// before\n$.normalize(html, {tags: {section: {attrs:{}}}});\n// after\n$.normalize(html, {hierarchy: ['div','section','p','a','b','i','br','img'], tags: {section: {attrs:{}}}});
Defensive patterns

Strategy: validation

Validate before calling

function validateNormalizeOpt(opt){\n  if (!Array.isArray(opt.hierarchy)) throw new Error('opt.hierarchy must be an array');\n  Object.keys(opt.tags || {}).forEach(function(name){\n    if (opt.hierarchy.indexOf(name) === -1)\n      throw new Error('tag "'+name+'" must be added to hierarchy');\n  });\n}\n// call validateNormalizeOpt(customOpt) before $.normalize(html, customOpt);

Type guard

function optIsConsistent(opt){ return Array.isArray(opt.hierarchy) && !!opt.tags && Object.keys(opt.tags).every(function(n){ return opt.hierarchy.indexOf(n) !== -1; }); }

Try / catch

try {\n  validateNormalizeOpt(customOpt);\n  $.normalize(html, customOpt);\n} catch (e) {\n  if (/missing hierarchy definition/.test(e.message)) {\n    console.error('Config error: add', e.message.match(/tag "([^"]+)"/)[1], 'to hierarchy');\n  } else { throw e; }\n}

Prevention

When it happens

Trigger: Calling $.normalize(html, customOpt) where customOpt (deep-merged over baseOpt) adds a tags entry (e.g. tags: {section: {...}}) without adding 'section' to the hierarchy array. Also triggered by typos in a tag name inside tags that don't match any hierarchy entry.

Common situations: Extending the normalizer to support new HTML tags (article, section, figure, custom elements) by only configuring tags; copying a partial customOpt example; deep-extend quirks where $.extend(true, baseOpt, customOpt) merges user tags into the base set while the user's hierarchy list omits base or new tags.

Related errors


AI-assisted analysis of amark/gun@552227599d (2026-09-02). Data as JSON: /api/errors/b95b862ac9afc770. Report an issue: GitHub.