{"record":{"id":"c074c84f6711d17d","repo":"1Panel-dev/1Panel","slug":"unexpected-end-of-file-while-scanning-a-string-ma","errorCode":null,"errorMessage":"unexpected end of file while scanning a string, maybe an unclosed lua code?","messagePattern":"unexpected end of file while scanning a string, maybe an unclosed lua code\\?","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agent/utils/nginx/parser/lexer.go","lineNumber":91,"sourceCode":"\t\treturn s.scanComment()\n\tcase ch == '$':\n\t\treturn s.scanVariable()\n\tcase isQuote(ch):\n\t\treturn s.scanQuotedString(ch)\n\tdefault:\n\t\treturn s.scanKeyword()\n\t}\n}\n\nfunc (s *lexer) scanLuaCode() flag.Flag {\n\tret := s.NewToken(flag.LuaCode)\n\tstack := make([]rune, 0, 50)\n\tcode := strings.Builder{}\n\n\tfor {\n\t\tch := s.read()\n\t\tif ch == rune(flag.EOF) {\n\t\t\tpanic(\"unexpected end of file while scanning a string, maybe an unclosed lua code?\")\n\t\t}\n\t\tif ch == '#' {\n\t\t\tcode.WriteRune(ch)\n\t\t\tcode.WriteString(s.readUntil(isEndOfLine))\n\t\t\tcontinue\n\t\t} else if ch == '}' {\n\t\t\tif len(stack) == 0 {\n\t\t\t\t_ = s.reader.UnreadRune()\n\t\t\t\treturn ret.Lit(strings.TrimRight(strings.Trim(code.String(), \"\\n\"), \"\\n  \"))\n\t\t\t}\n\t\t\tif stack[len(stack)-1] == '{' {\n\t\t\t\tstack = stack[0 : len(stack)-1]\n\t\t\t}\n\t\t} else if ch == '{' {\n\t\t\tstack = append(stack, ch)\n\t\t}\n\t\tcode.WriteRune(ch)\n\t}","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/1Panel-dev/1Panel/blob/5ac7c808815b0691009cd390414f03471312262f/agent/utils/nginx/parser/lexer.go#L73-L109","documentation":"Panic in the nginx-config lexer's scanLuaCode when EOF is hit while scanning a *_by_lua_block { ... } region — brace nesting tracked on a rune stack never closed, so the scanner ran off the end of the input. It is a hard parse error for unbalanced lua blocks.","triggerScenarios":"A config contains access_by_lua_block { ... with a missing closing '}' (or nested unbalanced braces inside the lua code), and the agent parses that file with agent/utils/nginx/parser.","commonSituations":"Hand-written WAF/rate-limit lua snippets with an extra '{' or a deleted '}'; truncated config after an interrupted save; copy-paste that dropped the last line.","solutions":["Open the file reported by the parse operation and balance the braces in the *_by_lua_block section (count { vs })","Validate before saving: nginx -t -c <file> or re-parse via the same agent parser in a test","Restore the previous config version from 1Panel's config history if the edit broke it"],"exampleFix":"# before\naccess_by_lua_block {\n  if x then\n    do_thing()\n# after\naccess_by_lua_block {\n  if x then\n    do_thing()\n  end\n}","handlingStrategy":"validation","validationCode":"python3 - <<'PY'\nimport sys\ntxt = open(sys.argv[1]).read()\nassert txt.count('{') == txt.count('}'), f\"unbalanced braces: {{={txt.count('{')} }}={txt.count('}')}\"\nprint('braces balanced')\nPY /opt/1panel/apps/openresty/openresty/conf/nginx.conf","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Balance-check braces (especially inside *_by_lua_block) before saving configs","Keep lua snippets small and test them in a standalone file first"],"tags":["nginx","lua","lexer","go","panic"],"backgroundTag":null,"analyzedSha":"5ac7c808815b0691009cd390414f03471312262f","analyzedAt":"2026-08-15T14:02:06.953Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}