amark/gun · error · Error

not tag in

Error message

not tag in ${a}

What it means

In lib/normalize.js (jquery-normalize), addUnstable is a callback passed into the mutation functions (exclude, next, parentOrderWrap) that re-queues a node's wrapper object `a` into the unstable list. Before queueing it asserts that the wrapper has a `tag` property; if `a.tag` is missing/falsy it throws 'not tag in '. Note the arguments to Error() are not interpolated, so the message literally reads 'not tag in ' — the offending object `a` is passed as a second, ignored argument.

Solutions

  1. Ensure every object passed to addUnstable went through initTag so a.tag is set.
  2. Check for empty elements (br, img) in the HTML being normalized — initTag returns early for them; don't re-queue their wrappers from custom mutations.
  3. If you supply custom opt.mutate functions, only call addUnstable on wrappers that already have a tag.
  4. Log the object before throwing (Error arguments beyond the first are ignored) to identify the offending node: temporarily change the throw to include JSON.stringify(a).
  5. Upgrade/patch the library — the message construction is buggy (comma instead of concatenation) which hides which tag caused it.

Example fix

// before\nif(!a.tag) { throw Error("not tag in ", a) }\n// after\nif(!a.tag) { throw Error("not tag in " + JSON.stringify(a && a.$ && a.$[0] && a.$[0].outerHTML)) }
Defensive patterns

Strategy: type-guard

Validate before calling

// Guard wrappers before any custom mutate hook re-queues them\nfunction canEnqueue(a){ return a && typeof a === 'object' && a.$ && a.$[0] && !!a.tag; }\n// only call addUnstable when canEnqueue(a) is true

Type guard

function hasTag(a){ return a != null && typeof a === 'object' && typeof a.tag === 'string' && a.tag.length > 0; }

Try / catch

try {\n  $.normalize(html, opt);\n} catch (e) {\n  if (/^not tag in/.test(e.message)) {\n    console.error('normalize state machine hit a wrapper without a tag — check empty elements or custom mutate hooks');\n  } else { throw e; }\n}

Prevention

When it happens

Trigger: A mutation function (exclude, next, or parentOrderWrap) calls addUnstable with an object `a` that never went through initTag, or whose `tag` was never assigned (initTag sets a.tag = tag(a.$); empty nodes return early before a.tag gets fully set up in the state machine path). Typically caused by custom/misconfigured opt.mutate hooks or DOM structures that bypass initTag.

Common situations: Custom normalize options supplying mutate functions that enqueue their own wrappers without a tag; HTML containing empty elements (empty(a) returns early in initTag, leaving a.tag unset) later manipulated by mutations; bugs after refactoring the internal state machine.

Related errors


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

Appendix: source

Thrown at lib/normalize.js:63

      'em': 'i', 'strong': 'b', 'strike': 's',
    }
    ,attrs: {
      'id':1
      ,'class':1
      ,'style':1
    }
    ,blockTag: function(a){
      return a.opt.tags[a.tag].order < a.opt.tags.a.order;
    }
    ,mutate: [exclude, moveSpaceUp, next, parentOrderWrap]
  }

  var defaultOpt = prepareOptTags($.extend(true, {}, baseOpt));

  var unstableList = [];

  function addUnstable(a) { // NOT ES5
    if(!a.tag) { throw Error("not tag in ", a) }
    if(a.unstable) return;
    unstableList.push(a);
    a.unstable = true;
  }

  function initTag(a) {
    // initial handling (container, convert, attributes):
    a.tag = tag(a.$);
      if(empty(a)) {
      return;
    }
    parseAndRemoveAttrs(a);
    convert(a);
    setAttrs(a);
    a.$[0].a = a; // link from dom element back to a
    // state machine init
    unstableList.push(a);
    a.unstable = true;

View on GitHub (pinned to 552227599d)