{"record":{"id":"717d2f5dd49a57e1","repo":"Shopify/liquid","slug":"unexpected-character-ss-getch","errorCode":null,"errorMessage":"Unexpected character #{ss.getch}","messagePattern":"Unexpected character #(.+?)","errorType":"exception","errorClass":"Liquid::SyntaxError","httpStatus":null,"severity":"error","filePath":"lib/liquid/lexer.rb","lineNumber":175,"sourceCode":"            else\n              raise_syntax_error(start_pos, ss)\n            end\n          end\n        end\n        # rubocop:enable Metrics/BlockNesting\n        output << EOS\n      rescue ::ArgumentError => e\n        if e.message == \"invalid byte sequence in #{ss.string.encoding}\"\n          raise SyntaxError, \"Invalid byte sequence in #{ss.string.encoding}\"\n        else\n          raise\n        end\n      end\n\n      def raise_syntax_error(start_pos, ss)\n        ss.pos = start_pos\n        # the character could be a UTF-8 character, use getch to get all the bytes\n        raise SyntaxError, \"Unexpected character #{ss.getch}\"\n      end\n    end\n  end\nend\n","sourceCodeStart":157,"sourceCodeEnd":180,"githubUrl":"https://github.com/Shopify/liquid/blob/807d45a6b3d4568e64e86b375e3702df2c7c860c/lib/liquid/lexer.rb#L157-L180","documentation":"When the lexer's regex scanner cannot match any known token, raise_syntax_error rewinds to the start position and raises Liquid::SyntaxError reporting the unexpected character (using getch so multi-byte UTF-8 characters are reported whole). It means the template contains a character that cannot begin any valid Liquid token.","triggerScenarios":"Template.parse on source containing a stray character that breaks tokenization — e.g. an unmatched '{' not followed by '%' or '{', invalid control characters, or garbage bytes near tag delimiters.","commonSituations":"Hand-edited templates with a lone '{' or '}' mishandled; copy-paste introducing smart quotes or invisible control characters; templating scripts emitting malformed delimiters (e.g. '{ x }' or '{- if -}').","solutions":["Locate the reported character in the template and fix or remove it (check for lone '{' or non-ASCII punctuation).","Fix the delimiter to a valid one: {% ... %}, {{ ... }}, or a raw '{' that does not look like a broken tag start.","Re-save the file as clean UTF-8 without smart quotes/control characters.","Add a parse smoke test (Template.parse) in CI for templates edited by hand."],"exampleFix":"// before\n{ if x %}hello{{\n// after\n{% if x %}hello{% endif %}","handlingStrategy":"validation","validationCode":"def no_lone_braces?(src)\n  !src.match?(/\\{(?![{%])/) # no '{' not followed by '{' or '%'\nend","typeGuard":null,"tryCatchPattern":"begin\n  Liquid::Template.parse(src)\nrescue Liquid::SyntaxError => e\n  if (ch = e.message[/Unexpected character (.+)/, 1])\n    report_syntax_location(src, ch)\n  end\n  raise\nend","preventionTips":["Escape literal braces in template text where needed.","Ban smart quotes/control characters in template files via editorconfig/lint.","Run Template.parse on every template in CI to catch tokenization breakage early.","Fix delimiters to exactly {% %} or {{ }} — beware typos like {- ... -}."],"tags":["ruby","liquid","lexer","syntax","tokenizer"],"backgroundTag":"invalid-argument-format","analyzedSha":"807d45a6b3d4568e64e86b375e3702df2c7c860c","analyzedAt":"2026-09-08T11:31:38.917Z","contentChangedAt":"2026-09-08T11:31:38.917Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}