{"record":{"id":"2bc7615d4ec801c6","repo":"dianping/cat","slug":"attribute-invalid-close-char","errorCode":null,"errorMessage":"attribute invalid close char('/')","messagePattern":"attribute invalid close char\\('/'\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cat-home/src/main/webapp/assets/js/editor/worker-xml.js","lineNumber":1556,"sourceCode":"\t\t\t}else{\n\t\t\t\tthrow new Error('attribute value must after \"=\"');\n\t\t\t}\n\t\t\tbreak;\n\t\tcase '/':\n\t\t\tswitch(s){\n\t\t\tcase S_TAG:\n\t\t\t\tel.setTagName(source.slice(start,p));\n\t\t\tcase S_E:\n\t\t\tcase S_S:\n\t\t\tcase S_C:\n\t\t\t\ts = S_C;\n\t\t\t\tel.closed = true;\n\t\t\tcase S_V:\n\t\t\tcase S_ATTR:\n\t\t\tcase S_ATTR_S:\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new Error(\"attribute invalid close char('/')\")\n\t\t\t}\n\t\t\tbreak;\n\t\tcase ''://end document\n\t\t\terrorHandler.error('unexpected end of input');\n\t\tcase '>':\n\t\t\tswitch(s){\n\t\t\tcase S_TAG:\n\t\t\t\tel.setTagName(source.slice(start,p));\n\t\t\tcase S_E:\n\t\t\tcase S_S:\n\t\t\tcase S_C:\n\t\t\t\tbreak;//normal\n\t\t\tcase S_V://Compatible state\n\t\t\tcase S_ATTR:\n\t\t\t\tvalue = source.slice(start,p);\n\t\t\t\tif(value.slice(-1) === '/'){\n\t\t\t\t\tel.closed  = true;\n\t\t\t\t\tvalue = value.slice(0,-1)","sourceCodeStart":1538,"sourceCodeEnd":1574,"githubUrl":"https://github.com/dianping/cat/blob/e815e74d4c2dd74edac831241f1253fcc7d25381/cat-home/src/main/webapp/assets/js/editor/worker-xml.js#L1538-L1574","documentation":"A '/' encountered inside a start tag in a state where self-closing is not meaningful (worker-xml.js:~1556). The '/' case tolerates states S_TAG..S_ATTR_S (empty-element close after tag name or attributes) but any other state — notably S_EQ, i.e. '/' immediately after '=' with no value — hits the default and throws.","triggerScenarios":"'<a href=/> ...' (self-closing right after '='), or a slash embedded mid-attribute in a state the switch doesn't list. The case '/' default at line 1552-1555 throws.","commonSituations":"Typing an empty-element tag and the worker parses before the value is written; HTML like '<br/>' pasted with a mangled attribute ('<img src=/>'); templating that collapses an attribute value to nothing.","solutions":["Complete the attribute value before the slash: <a href=\"#\"/> or drop the attribute.","If the tag should be empty, remove the dangling 'attr=' part entirely.","Re-check the tag after finishing the edit — this is often a transient mid-keystroke state."],"exampleFix":"<!-- before -->\n<img src=/>\n\n<!-- after -->\n<img src=\"placeholder.png\"/>","handlingStrategy":"validation","validationCode":"// No '/' may directly follow '=' inside a start tag:\nfunction noSlashAfterEquals(tagText) {\n  return !/=\\s*\\//.test(tagText);\n}","typeGuard":null,"tryCatchPattern":"try {\n  parseStartTag(source, start, tagNameReplacer);\n} catch (ex) {\n  if (/invalid close char/.test(ex.message)) reportXmlError(ex); else throw ex;\n}","preventionTips":["Finish attribute values before typing '/>'.","Delete dangling 'attr=' if the attribute is unused.","Let the editor's autoclose produce '/>' atomically."],"tags":["xml","sax","ace-editor","self-closing","parser"],"backgroundTag":null,"analyzedSha":"e815e74d4c2dd74edac831241f1253fcc7d25381","analyzedAt":"2026-08-14T14:22:34.512Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}