{"record":{"id":"ca1b5b373828a486","repo":"dianping/cat","slug":"invalid-attribute-qname","errorCode":null,"errorMessage":"invalid attribute:{qName}","messagePattern":"invalid attribute:(.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cat-home/src/main/webapp/assets/js/editor/worker-xml.js","lineNumber":1800,"sourceCode":"\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\n\n\nfunction _set_proto_(thiz,parent){\n\tthiz.__proto__ = parent;\n\treturn thiz;\n}","sourceCodeStart":1782,"sourceCodeEnd":1818,"githubUrl":"https://github.com/dianping/cat/blob/e815e74d4c2dd74edac831241f1253fcc7d25381/cat-home/src/main/webapp/assets/js/editor/worker-xml.js#L1782-L1818","documentation":"ElementAttributes.add (worker-xml.js:1797-1803) validates every attribute name against the same tagNamePattern regex used for element names and throws on mismatch. An attribute name must be an XML Name: it cannot start with a digit, contain quotes, spaces, '=', '/', or '>'.","triggerScenarios":"Attributes like '<a 1href=\"x\">' (leading digit), '<a href\"x\">' (missing '=' makes the parser slice a name containing a quote), or names with stray punctuation. The add() test at line 1799-1801 throws.","commonSituations":"A missing '=' before a value causes the quote to be absorbed into the next name slice; copy-paste of HTML with weird attribute names; find/replace that deleted '=' characters; PHP/ASP-style short tags fed to a strict XML worker.","solutions":["Check the attribute flagged in the message: give it a valid Name and a proper '=' and quoted value.","If the name contains a quote character, the '=' before the preceding value is missing — restore it.","Run the document through xmllint for a full list of malformed attributes."],"exampleFix":"<!-- before -->\n<link href\"stylesheet.css\">\n\n<!-- after -->\n<link href=\"stylesheet.css\">","handlingStrategy":"type-guard","validationCode":"// Validate attribute names before adding them:\nfunction attrNameOk(name) {\n  return /^[A-Za-z_:][-A-Za-z0-9_:.]*$/.test(name);\n}\nfor (const k of Object.keys(attrs)) {\n  if (!attrNameOk(k)) throw new TypeError('Invalid attribute name: ' + k);\n}","typeGuard":"function isValidXmlAttribute(s) {\n  return typeof s === 'string' && /^[A-Za-z_:][-A-Za-z0-9_:.]*$/.test(s) && !/[\\s='\\\"/<>]/.test(s);\n}","tryCatchPattern":"try {\n  el.add(qName, value, offset);\n} catch (ex) {\n  if (/invalid attribute/.test(ex.message)) reportXmlError(ex); else throw ex;\n}","preventionTips":["Apply isValidXmlAttribute() to every generated attribute name.","If a name contains a quote, the preceding attribute is missing '=' — fix that first.","Prefer DOM APIs or a serializer over string-built XML."],"tags":["xml","sax","ace-editor","attributes","parser"],"backgroundTag":null,"analyzedSha":"e815e74d4c2dd74edac831241f1253fcc7d25381","analyzedAt":"2026-08-14T14:22:34.512Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}