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

  1. Add the missing closing quote character shown in the message (the message names it, e.g. '\' or \"").
  2. When generating XML, escape quotes inside values (" / ') or use the opposite quote type to wrap.
  3. 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

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


AI-assisted analysis of dianping/cat@e815e74d4c (2026-08-14). Data as JSON: /api/errors/ca88fc0e38e824a3. Report an issue: GitHub.