{"record":{"id":"d0ad1095c055bc78","repo":"Meituan-Dianping/mpvue","slug":"tag-tag-has-no-matching-end-tag","errorCode":null,"errorMessage":"tag <${tag}> has no matching end tag.","messagePattern":"tag <(.+?)> has no matching end tag\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/weex-template-compiler/build.js","lineNumber":520,"sourceCode":"    if (tagName) {\n      for (pos = stack.length - 1; pos >= 0; pos--) {\n        if (stack[pos].lowerCasedTag === lowerCasedTagName) {\n          break\n        }\n      }\n    } else {\n      // If no tag name is provided, clean shop\n      pos = 0;\n    }\n\n    if (pos >= 0) {\n      // Close all the open elements, up the stack\n      for (var i = stack.length - 1; i >= pos; i--) {\n        if (process.env.NODE_ENV !== 'production' &&\n          (i > pos || !tagName) &&\n          options.warn\n        ) {\n          options.warn(\n            (\"tag <\" + (stack[i].tag) + \"> has no matching end tag.\")\n          );\n        }\n        if (options.end) {\n          options.end(stack[i].tag, start, end);\n        }\n      }\n\n      // Remove the open elements from the stack\n      stack.length = pos;\n      lastTag = pos && stack[pos - 1].tag;\n    } else if (lowerCasedTagName === 'br') {\n      if (options.start) {\n        options.start(tagName, [], true, start, end);\n      }\n    } else if (lowerCasedTagName === 'p') {\n      if (options.start) {\n        options.start(tagName, [], false, start, end);","sourceCodeStart":502,"sourceCodeEnd":538,"githubUrl":"https://github.com/Meituan-Dianping/mpvue/blob/6c5d78ee04f58c6d782c456dfcf0fe63c0b7f89b/packages/weex-template-compiler/build.js#L502-L538","documentation":"This dev-mode warning is emitted by the HTML parser's parseEndTag when a closing tag does not match any open element in the parser's element stack. The parser closes every remaining element above the mismatch point via options.end, and warns for each one left without a matching end tag. It indicates malformed template markup (unclosed or wrongly nested tags).","triggerScenarios":"Compiling a template where an element is never closed, or end tags appear out of nesting order, so parseEndTag finds no stack entry matching the closing tag name (warn fires when i > pos or tagName is empty and options.warn is set).","commonSituations":"Hand-written templates with <div> opened but not closed, self-closing a non-void tag incorrectly, or JSX-like nesting mistakes; often after copy-pasting markup or refactoring without closing a wrapper element.","solutions":["Add the missing end tag for the element named in the warning","Reorder the end tags so nesting matches the start tags","Validate the template HTML in an editor/linter before compiling"],"exampleFix":"// before\n<div><span>hi</div>\n// after\n<div><span>hi</span></div>","handlingStrategy":"validation","validationCode":"function checkBalancedTags(template) {\n  const voidTags = new Set(['area','base','br','col','embed','hr','img','input','link','meta','param','source','track','wbr']);\n  const stack = [];\n  const re = /<\\/?([a-zA-Z][\\w-]*)[^>]*?(\\/?)>/g;\n  let m;\n  while ((m = re.exec(template))) {\n    const [full, tag, selfClose] = m;\n    if (full.startsWith('</')) {\n      if (stack.pop() !== tag) return `mismatched end tag </${tag}>`;\n    } else if (!selfClose && !voidTags.has(tag.toLowerCase())) {\n      stack.push(tag);\n    }\n  }\n  return stack.length ? `unclosed tag <${stack[stack.length-1]}>` : null;\n}","typeGuard":"function isTemplateBalanced(template) {\n  return typeof template === 'string' && checkBalancedTags(template) === null;\n}","tryCatchPattern":null,"preventionTips":["Run templates through an HTML linter (eslint-plugin-vue, HTMLHint) before compiling","Keep templates small so nesting mistakes are easy to spot","Use editor auto-close-tag features to avoid unclosed elements"],"tags":["template","html-parser","vue","weex"],"backgroundTag":"unclosed-template-tag","analyzedSha":"6c5d78ee04f58c6d782c456dfcf0fe63c0b7f89b","analyzedAt":"2026-09-02T05:17:40.946Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T11:17:12.671Z"}