{"record":{"id":"060b8e727f83bfc9","repo":"dianping/cat","slug":"invalid-tagname-tagname","errorCode":null,"errorMessage":"invalid tagName:{tagName}","messagePattern":"invalid tagName:(.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cat-home/src/main/webapp/assets/js/editor/worker-xml.js","lineNumber":1794,"sourceCode":"\tif(end){\n\t\tvar match = source.substring(start,end).match(/^<\\?(\\S*)\\s*([\\s\\S]*?)\\s*$/);\n\t\tif(match){\n\t\t\tvar len = match[0].length;\n\t\t\tdomBuilder.processingInstruction(match[1], match[2]) ;\n\t\t\treturn end+2;\n\t\t}else{//error\n\t\t\treturn -1;\n\t\t}\n\t}\n\treturn -1;\n}\nfunction ElementAttributes(source){\n\t\n}\nElementAttributes.prototype = {\n\tsetTagName:function(tagName){\n\t\tif(!tagNamePattern.test(tagName)){\n\t\t\tthrow new Error('invalid tagName:'+tagName)\n\t\t}\n\t\tthis.tagName = tagName\n\t},\n\tadd:function(qName,value,offset){\n\t\tif(!tagNamePattern.test(qName)){\n\t\t\tthrow new Error('invalid attribute:'+qName)\n\t\t}\n\t\tthis[this.length++] = {qName:qName,value:value,offset:offset}\n\t},\n\tlength:0,\n\tgetLocalName:function(i){return this[i].localName},\n\tgetOffset:function(i){return this[i].offset},\n\tgetQName:function(i){return this[i].qName},\n\tgetURI:function(i){return this[i].uri},\n\tgetValue:function(i){return this[i].value}\n}\n\n","sourceCodeStart":1776,"sourceCodeEnd":1812,"githubUrl":"https://github.com/dianping/cat/blob/e815e74d4c2dd74edac831241f1253fcc7d25381/cat-home/src/main/webapp/assets/js/editor/worker-xml.js#L1776-L1812","documentation":"ElementAttributes.setTagName (worker-xml.js:1791-1796) validates each parsed tag name against tagNamePattern (built from nameStartChar/nameChar regexes, line 1338) and throws if it doesn't match. The pattern encodes the XML Name production: must start with a letter, '_', or ':', followed by name characters — so names beginning with a digit, or containing spaces/'='/'\"', are rejected.","triggerScenarios":"Start tags like '<1abc>', '<-foo>', '<foo bar>' (space makes the slice 'foo bar' invalid), or names with invalid punctuation. The setTagName call from the '/'/'>' cases passes the sliced text to the test and throws at line 1793-1795.","commonSituations":"Tag-name/attribute boundary confusion from a missing quote or '=' earlier in the tag, CMS-generated pseudo-tags, template placeholders as tag names, or HTML custom-element names with unusual characters.","solutions":["Rename the element so it starts with a letter or underscore and contains only name characters (letters, digits, '-', '_', '.', ':').","If the reported 'tagName' contains spaces or '=', the real bug is earlier in the tag — fix the malformed attribute that made the slice too long.","Validate with xmllint to catch the root malformed tag."],"exampleFix":"<!-- before -->\n<2col-layout>...</2col-layout>\n\n<!-- after -->\n<col-layout-2>...</col-layout-2>","handlingStrategy":"validation","validationCode":"// Reuse the worker's own pattern shape to pre-validate tag names:\nconst NAME = /^[A-Za-z_:][-A-Za-z0-9_:.]*$/;\nfunction tagNameOk(name) { return NAME.test(name); }\ntagNameOk('col-2');   // true\ntagNameOk('2col');    // false","typeGuard":"function isValidXmlName(s) {\n  return typeof s === 'string' && /^[A-Za-z_:][-A-Za-z0-9_:.]*$/.test(s);\n}","tryCatchPattern":"try {\n  el.setTagName(name);\n} catch (ex) {\n  if (/invalid tagName/.test(ex.message)) reportXmlError(ex); else throw ex;\n}","preventionTips":["Tag names start with a letter or '_'; never a digit or '-'.","If the reported name contains spaces/quotes, suspect a broken attribute earlier in the tag.","Validate names with isValidXmlName() before generating elements programmatically."],"tags":["xml","sax","ace-editor","tag-name","parser"],"backgroundTag":null,"analyzedSha":"e815e74d4c2dd74edac831241f1253fcc7d25381","analyzedAt":"2026-08-14T14:22:34.512Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}