dianping/cat · error · Error
attribute value no end '{c}' match
Error message
attribute value no end '{c}' match What it means
Unrecoverable unterminated attribute value in the XML worker's attribute tokenizer (worker-xml.js:~1530). After seeing attrName '=', the scanner hits a quote and searches for the matching closing quote with source.indexOf; if none exists in the rest of the document, it cannot locate the value's end and throws instead of guessing.
Source
Thrown at cat-home/src/main/webapp/assets/js/editor/worker-xml.js:1530
attrName = source.slice(start,p);
s = S_EQ;
}else if(s === S_ATTR_S){
s = S_EQ;
}else{
throw new Error('attribute equal must after attrName');
}
break;
case '\'':
case '"':
if(s === S_EQ){//equal
start = p+1;
p = source.indexOf(c,start)
if(p>0){
value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
el.add(attrName,value,start-1);
s = S_E;
}else{
throw new Error('attribute value no end \''+c+'\' match');
}
}else if(s == S_V){
value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
el.add(attrName,value,start);
errorHandler.warning('attribute "'+attrName+'" missed start quot('+c+')!!');
start = p+1;
s = S_E
}else{
throw new Error('attribute value must after "="');
}
break;
case '/':
switch(s){
case S_TAG:
el.setTagName(source.slice(start,p));
case S_E:
case S_S:
case S_C:View on GitHub (pinned to e815e74d4c)
Solutions
- Add the missing closing quote character shown in the message (the message names it, e.g. '\' or \"").
- When generating XML, escape quotes inside values (" / ') or use the opposite quote type to wrap.
- While typing, ignore the transient error — it clears once the value is closed.
Example fix
<!-- before --> <img src="logo.png alt="logo"> <!-- after --> <img src="logo.png" alt="logo">
Defensive patterns
Strategy: validation
Validate before calling
// Verify every attribute value in a tag string is closed before parsing:
function quotesBalanced(tagText) {
for (const q of ['\"', "'"]) {
const parts = tagText.split(q);
// inside a tag, quotes must appear in pairs
if (parts.length % 2 === 0) return false;
}
return true;
} Try / catch
try {
parseStartTag(source, start, tagNameReplacer);
} catch (ex) {
if (/no end .+ match/.test(ex.message)) reportUnterminatedValue(ex); else throw ex;
} Prevention
- Type both quotes first, then fill the value.
- Escape embedded quotes as "/' in generated XML.
- Prefer an XML builder (DOM serialization) over string concatenation.
When it happens
Trigger: A start tag whose attribute value quote is never closed: '<a href="http://x>' with the closing double quote missing, or a single-quoted value containing a stray unescaped construct so indexOf lands past EOF. The 'if (p>0) ... else throw' at line 1526-1530 fires.
Common situations: Mid-edit state while typing in the editor (worker parses before you type the closing quote), quotes stripped by naive string concatenation or minifiers, attribute values containing the quote character unescaped in generated XML.
Related errors
- attribute equal must after attrName
- attribute value must after "="
- attribute value missed!!
- invalid attribute:{qName}
- attribute invalid close char('/')
AI-assisted analysis of dianping/cat@e815e74d4c (2026-08-14).
Data as JSON: /api/errors/ca88fc0e38e824a3.
Report an issue: GitHub.