{"record":{"id":"b6f8fee0dd327e1d","repo":"amark/gun","slug":"order-of-name-not-defined-in-hierarchy","errorCode":null,"errorMessage":"Order of '${name}' not defined in hierarchy","messagePattern":"Order of '(.+?)' not defined in hierarchy","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/normalize.js","lineNumber":112,"sourceCode":"    }\n  }\n\n  function prepareOptTags(opt) {\n    var name, tag, tags = opt.tags;\n    for(name in tags) {\n      if(opt.hierarchy.indexOf(name)===-1)\n        throw Error('tag \"'+name+'\" is missing hierarchy definition');\n    }\n    opt.hierarchy.forEach(function(name){\n      if(!tags[name]){\n        tags[name] = {attrs: opt.attrs};\n      }\n      (tag=tags[name]).attrs = $.extend(tag.attrs||{}, opt.attrs);\n      tag.name = name; // not used, debug help (REMOVE later?)\n      // order\n      tag.order = opt.hierarchy.indexOf(name)\n      if(tag.order === -1) {\n      throw Error(\"Order of '\"+name+\"' not defined in hierarchy\");\n    }\n    });\n    return opt;\n  }\n\n  // GENERAL UTILS\n\n  function get(o, args){ // path arguments as separate string parameters\n    if(typeof args === 'string')\n      return o[args[0]];\n    var i = 0, l = args.length, u;\n    while((o = o[args[i++]]) != null && i < l){};\n    return i < l ? u : o;\n  }\n\n  function has(obj,prop){\n    return Object.prototype.hasOwnProperty.call(obj, prop);\n  }","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/amark/gun/blob/552227599d47ba0493824b7fcf8a00c8cd6404ba/lib/normalize.js#L94-L130","documentation":"Within prepareOptTags, after building each tag entry, the code assigns tag.order = opt.hierarchy.indexOf(name) and throws if it is -1. Since the forEach iterates hierarchy itself, this is a defensive invariant: it fires when a name in the hierarchy cannot be found in itself, i.e. the hierarchy array contains a falsy/duplicate-corrupted entry or the name resolved via a mutated tags map doesn't match — practically signaling an inconsistent or malformed hierarchy definition.","triggerScenarios":"Passing customOpt with a hierarchy array containing null/undefined or non-string entries (indexOf on the string name then mismatches), or an opt object where tags/hierarchy were programmatically corrupted between the tags-loop check and the order assignment; also via defaultOpt if baseOpt were patched inconsistently.","commonSituations":"Dynamically generated hierarchy arrays where a variable is undefined; hierarchy arrays built with duplicates or holes (sparse arrays); runtime mutation of the shared baseOpt object; framework integration code assembling options from user input.","solutions":["Ensure the hierarchy array contains only valid, non-empty string tag names with no holes.","Build the hierarchy from a fixed literal list rather than dynamic string concatenation that may inject undefined.","Sanitize: filter the hierarchy (opt.hierarchy = opt.hierarchy.filter(Boolean)) and deduplicate before calling $.normalize.","Verify customOpt isn't accidentally mutating the shared baseOpt; construct options from $.extend(true, {}, baseOpt, customOpt).","Cross-check both validations: first fix any 'missing hierarchy definition' errors, then re-test — the two checks share the same opt object."],"exampleFix":"// before\\nhierarchy: ['div', null, 'p', undefined, 'a']  // sparse entries\\n// after\\nhierarchy: ['div', 'pre', 'p', 'a']            // clean, ordered tag list","handlingStrategy":"validation","validationCode":"function validateHierarchy(hierarchy){\\n  if (!Array.isArray(hierarchy)) throw new Error('hierarchy must be an array');\\n  var seen = {};\\n  for (var i = 0; i < hierarchy.length; i++) {\\n    var n = hierarchy[i];\\n    if (typeof n !== 'string' || !n) throw new Error('invalid hierarchy entry at index '+i);\\n    if (seen[n]) throw new Error('duplicate hierarchy entry: '+n);\\n    seen[n] = true;\\n  }\\n}\\n// call validateHierarchy(customOpt.hierarchy) before $.normalize(html, customOpt);","typeGuard":"function isCleanHierarchy(h){ return Array.isArray(h) && h.every(function(n){ return typeof n === 'string' && n.length > 0; }) && new Set(h).size === h.length; }","tryCatchPattern":"try {\\n  $.normalize(html, customOpt);\\n} catch (e) {\\n  if (/not defined in hierarchy/.test(e.message)) {\\n    console.error('Hierarchy corrupted — rebuild opt from baseOpt:', e.message);\\n    opt = prepareOptTags($.extend(true, {}, baseOpt, userOpt)); // retry with a clean copy\\n  } else { throw e; }\\n}","preventionTips":["Build hierarchy arrays from literals; avoid dynamic assembly that can inject undefined.","Never mutate baseOpt or a shared opt in place; deep-clone with $.extend(true, {}, baseOpt).","Filter/dedupe hierarchy before passing: hierarchy.filter(Boolean).","Keep both hierarchy checks (tags coverage + order) covered by the same config unit tests."],"tags":["configuration","normalization","hierarchy","options"],"backgroundTag":"missing-hierarchy-definition","analyzedSha":"552227599d47ba0493824b7fcf8a00c8cd6404ba","analyzedAt":"2026-09-02T18:40:58.370Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T21:17:11.164Z"}