dianping/cat · error · Error

attribute value must after "="

Error message

attribute value must after "="

What it means

Quote character in an illegal position in the XML worker's attribute state machine (worker-xml.js:~1539). Quotes are only meaningful right after '=' (S_EQ, opening a value) or while scanning an unquoted value (S_V). A quote in any other state — before '=', after a completed value, inside a name — is a hard error.

Source

Thrown at cat-home/src/main/webapp/assets/js/editor/worker-xml.js:1539

		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:
				s = S_C;
				el.closed = true;
			case S_V:
			case S_ATTR:
			case S_ATTR_S:
				break;
			default:
				throw new Error("attribute invalid close char('/')")
			}

View on GitHub (pinned to e815e74d4c)

Solutions

  1. Rewrite the start tag in well-formed form: name="value" pairs only.
  2. Check for stray/typographic quote characters in the flagged tag and replace with ASCII quotes.
  3. Validate the document with xmllint to see all malformed spots at once.

Example fix

<!-- before -->
<input "text" value="1">

<!-- after -->
<input type="text" value="1">
Defensive patterns

Strategy: validation

Validate before calling

// Reject quotes that appear anywhere except around a value:
function tagShapeOk(tagText) {
  const body = tagText.replace(/^<\s*[\w:.-]+/, '').replace(/\/?\s*>$/, '');
  const attrs = body.trim();
  if (!attrs) return true;
  return attrs.split(/\s+(?=[\w:.-]+\s*=)/).every(a => /^[\w:.-]+\s*=\s*("[^"]*"|'[^']*'|\S+)$/.test(a));
}

Try / catch

try {
  parseStartTag(source, start, tagNameReplacer);
} catch (ex) {
  if (/attribute value must after/.test(ex.message)) reportXmlError(ex); else throw ex;
}

Prevention

When it happens

Trigger: Malformed tags like '<tag "foo">' (quoted name), '<tag a="1" "2">' (second value with no attribute), or '<tag a= "1" 2="3">' sequences. Both quote cases at line 1518-1523 fall through to the else at line 1537-1539 and throw.

Common situations: HTML habits carried into strict XML (e.g. quoted attribute names), broken find/replace over attributes, or paste of rich text that turned apostrophes into typographic quotes (‘ ’) adjacent to attributes.

Related errors


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