{"record":{"id":"9fb803aa1124e89a","repo":"jdx/mise","slug":"tag-parsing-loop-reached-loop-limit-d-consider","errorCode":null,"errorMessage":"Tag parsing loop reached loop limit (%d). Consider either increasing it or checking HTML-code for syntax errors","messagePattern":"Tag parsing loop reached loop limit \\((.+?)\\)\\. Consider either increasing it or checking HTML-code for syntax errors","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/vfox/lua/htmlparser.lua","lineNumber":173,"sourceCode":"\t\topenstart, tpos, name = root._text:find(\n\t\t\t\"<\" ..        -- an uncaptured starting \"<\"\n\t\t\t\"([%w-]+)\" .. -- name = the first word, directly following the \"<\"\n\t\t\t\"[^>]*>\",     -- include, but not capture everything up to the next \">\"\n\t\ttpos)\n\t\tdbg(\"[MainLoop]:#LINE# openstart=%s || tpos=%s || name=%s\",str(openstart),str(tpos),str(name))\n\t\t-- }}}\n\t\tif not name then break end\n\t\t-- Some more vars {{{\n\t\tindex = index + 1\n\t\tlocal tag = ElementNode:new(index, str(name), (node or {}), descend, openstart, tpos)\n\t\tnode = tag\n\t\tlocal tagloop\n\t\tlocal tagst, apos = tag:gettext(), 1\n\t\t-- }}}\n\t\twhile true do -- TagLoop {{{\n\t\t\tdbg(\"[TagLoop]:#LINE# tag.name=%s, tagloop=%s\",str(tag.name),str(tagloop))\n\t\t\tif tagloop == limit then -- {{{\n\t\t\t\terr(\"Tag parsing loop reached loop limit (%d). Consider either increasing it or checking HTML-code for syntax errors\", limit)\n\t\t\t\tbreak\n\t\t\tend -- }}}\n\t\t\t-- Attrs {{{\n\t\t\tlocal start, k, eq, quote, v, zsp\n\t\t\tstart, apos, k, zsp, eq, zsp, quote = tagst:find(\n\t\t\t\t\"%s+\" ..         -- some uncaptured space\n\t\t\t\t\"([^%s=/>]+)\" .. -- k = an unspaced string up to an optional \"=\" or the \"/\" or \">\"\n\t\t\t\t\"([%s]-)\"..      -- zero or more spaces\n\t\t\t\t\"(=?)\" ..        -- eq = the optional; \"=\", else \"\"\n\t\t\t\t\"([%s]-)\"..      -- zero or more spaces\n\t\t\t\t[=[(['\"]?)]=],      -- quote = an optional \"'\" or '\"' following the \"=\", or \"\"\n\t\t\tapos)\n\t\t\tdbg(\"[TagLoop]:#LINE# start=%s || apos=%s || k=%s || zsp='%s' || eq='%s', quote=[%s]\",str(start),str(apos),str(k),str(zsp),str(eq),str(quote))\n\t\t\t-- }}}\n\t\t\tif not k or k == \"/>\" or k == \">\" then break end\n\t\t\t-- Pattern {{{\n\t\t\tif eq == \"=\" then\n\t\t\t\tlocal pattern = \"=([^%s>]*)\"","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/crates/vfox/lua/htmlparser.lua#L155-L191","documentation":"Within the main loop, each tag's attributes are parsed in an inner `TagLoop` that also has a limit guard. When attribute scanning for a tag iterates to the limit, it emits \"Tag parsing loop reached loop limit (%d)\" and breaks — the tag's attributes are only partially parsed, which almost always indicates malformed attribute markup.","triggerScenarios":"Parsing a tag whose attribute region confuses the scanner (unterminated quotes, stray '=' or '<' inside attribute values) so the TagLoop keeps advancing until `tagloop == limit`.","commonSituations":"HTML with unclosed quoted attribute values; script/style bodies containing markup-like text; plugin input mixing code snippets into attribute positions.","solutions":["Fix the HTML's attribute quoting/syntax (close all quotes, escape '<' inside values).","Increase the `limit` if the tag legitimately has an enormous number of attributes.","Sanitize or strip the offending tag region before parsing.","Extract attributes with a stricter regex for the known input format instead of the generic parser."],"exampleFix":"// before\n<div data-x=\"unterminated>...</div>  -- TagLoop hits limit\n// after\n<div data-x=\"unterminated\">...</div>  -- well-formed attributes parse cleanly","handlingStrategy":"validation","validationCode":"-- quick sanity check that quotes inside the payload are balanced\nlocal _, q = html:gsub('\"',\"\")\nif q % 2 == 1 then return nil, \"unbalanced quotes in HTML\" end","typeGuard":"local function balanced_quotes(s) local _, n = s:gsub('\"',\"\"); return n % 2 == 0 end","tryCatchPattern":null,"preventionTips":["Ensure attribute values are properly quoted and closed.","Avoid parsing mixed content (code inside attributes).","Increase the limit only after confirming the input is well-formed."],"tags":["lua","vfox","htmlparser","parsing"],"backgroundTag":"internal-invariant-violation","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}