{"record":{"id":"d85594acb497509c","repo":"jdx/mise","slug":"main-loop-reached-loop-limit-d-consider-either","errorCode":null,"errorMessage":"Main loop reached loop limit (%d). Consider either increasing it or checking HTML-code for syntax errors","messagePattern":"Main 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":150,"sourceCode":"\t\t\t\t\"(\"..\n\t\t\t\t(tpr[\"<\"] or \"__FAILED__\").. -- Here we search for \"<\", we escaped in previous gsub (and don't break things if we have no escaping replacement)\n\t\t\t\t\")(\"..\n\t\t\t\t(opts.tpl_marker_pattern or \"[^%w%s]\").. -- Capture templating symbol\n\t\t\t\t\")([%g%s]-)\".. -- match placeholder's content\n\t\t\t\t\"(%2)(>)\".. -- placeholder's tail\n\t\t\t\t\"([^>]*>)\", -- remaining\n\t\t\t\tfunction(...)return g(5,...)end\n\t\t\t)\n\t\t-- }}}\n\tend -- }}}\n\n\tlocal index = 0\n\tlocal root = ElementNode:new(index, str(text))\n\tlocal node, descend, tpos, opentags = root, true, 1, {}\n\n\twhile true do -- MainLoop {{{\n\t\tif index == limit then -- {{{\n\t\t\terr(\"Main loop reached loop limit (%d). Consider either increasing it or checking HTML-code for syntax errors\", limit)\n\t\t\tbreak\n\t\tend -- }}}\n\t\t-- openstart/tpos Definitions {{{\n\t\tlocal openstart, name\n\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","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/crates/vfox/lua/htmlparser.lua#L132-L168","documentation":"htmlparser.lua's main parsing loop (`MainLoop`) guards against infinite loops by counting parsed nodes against `limit`. When the node index reaches the limit, it reports \"Main loop reached loop limit (%d)\" and breaks, returning a partial tree rather than hanging forever — usually meaning malformed/pathological HTML.","triggerScenarios":"Calling the htmlparser parse function on input where the main loop keeps finding nodes until the configured limit is hit — deeply nested, malformed, truncated, or extremely large documents.","commonSituations":"vfox plugins parsing huge or broken HTML responses; truncated HTML from failed downloads; minified markup that never terminates cleanly.","solutions":["Check the input HTML for syntax errors (unclosed tags, truncation) and fix or fetch it again.","Increase the loop `limit` argument when legitimately parsing very large documents.","Pre-validate the payload (content-type/size checks) before parsing.","Truncate or chunk the document if it is simply too big."],"exampleFix":"// before\nlocal root = htmlparser.parse(bigHtml)  -- default limit hit\n// after\nlocal root = htmlparser.parse(bigHtml, nil, 50000)  -- raise loop limit","handlingStrategy":"validation","validationCode":"-- bail early on implausibly large or truncated input before parsing\nif #html > MAX_INPUT or not html:find(\"<\") then return nil, \"input too large or not HTML\" end","typeGuard":"local function looks_truncated(s) return type(s) == \"string\" and (s:find(\"<\") and not s:find(\">\")) end","tryCatchPattern":null,"preventionTips":["Validate that downloaded HTML is complete (content-length, closing tags).","Raise the loop limit for legitimately large documents.","Reject non-HTML content types before parsing."],"tags":["lua","vfox","htmlparser","limit"],"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-14T00:17:10.932Z"}