amark/gun · error · Error
not tag in ${a}
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.
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)
Solutions
- Ensure every object passed to addUnstable went through initTag so a.tag is set.
- 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.
- If you supply custom opt.mutate functions, only call addUnstable on wrappers that already have a tag.
- 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).
- 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
- Don't call addUnstable on wrappers that skipped initTag (empty tags like br/img return early).
- When writing custom opt.mutate functions, only re-queue objects produced by initTag.
- Include the node's outerHTML in error logs — Error() ignores extra args, so augment the message locally.
- Keep HTML input free of malformed/empty edge-case elements, or handle them in mutations.
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.