Shopify/liquid · error · Liquid::TemplateEncodingError

errors.syntax.invalid_template_encoding

errors.syntax.invalid_template_encoding

Error message

parse_context.locale.t("errors.syntax.invalid_template_encoding")

What it means

Template#parse validates the encoding of the source string before tokenizing. If source.valid_encoding? is false it raises Liquid::TemplateEncodingError with the localized errors.syntax.invalid_template_encoding message, because Liquid cannot tokenize bytes that do not form valid text in the string's declared encoding.

Solutions

  1. Re-encode the source before parsing: source.encode(Encoding::UTF_8, invalid: :replace, undef: :replace).
  2. Read template files with the correct encoding: File.read(path, encoding: 'UTF-8') or force_encoding when the true encoding is known.
  3. Fix the upstream data source so stored template bytes match their declared encoding.

Example fix

// before
Liquid::Template.parse(File.binread('template.liquid'))
// after
source = File.read('template.liquid', encoding: 'UTF-8')
Liquid::Template.parse(source.valid_encoding? ? source : source.encode(Encoding::UTF_8, invalid: :replace, undef: :replace))
Defensive patterns

Strategy: validation

Validate before calling

source = source.to_s
raise Liquid::TemplateEncodingError, 'invalid encoding' unless source.valid_encoding?

Type guard

def valid_template_source?(str)
  str.is_a?(String) && str.valid_encoding?
end

Try / catch

begin
  Liquid::Template.parse(source)
rescue Liquid::TemplateEncodingError => e
  source = source.dup.force_encoding(Encoding::UTF_8).scrub
  retry
end

Prevention

When it happens

Trigger: Calling Liquid::Template.parse with a String whose encoding label (e.g. UTF-8) does not match its actual bytes — typically binary data read as UTF-8, or files written in another encoding (ISO-8859-1, UTF-16) but tagged UTF-8.

Common situations: Reading template files without specifying encoding on systems with non-UTF-8 locale; concatenating binary attachments into template source; database columns storing non-UTF-8 bytes.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of Shopify/liquid@807d45a6b3 (2026-09-08). Data as JSON: /api/errors/b20204c20def6494. Report an issue: GitHub.

Appendix: source

Thrown at lib/liquid/template.rb:103

        environment = options[:environment] || Environment.default
        new(environment: environment).parse(source, options)
      end
    end

    def initialize(environment: Environment.default)
      @environment = environment
      @rethrow_errors  = false
      @resource_limits = ResourceLimits.new(environment.default_resource_limits)
    end

    # Parse source code.
    # Returns self for easy chaining
    def parse(source, options = {})
      parse_context = configure_options(options)
      source = source.to_s.to_str

      unless source.valid_encoding?
        raise TemplateEncodingError, parse_context.locale.t("errors.syntax.invalid_template_encoding")
      end

      tokenizer     = parse_context.new_tokenizer(source, start_line_number: @line_numbers && 1)
      @root         = Document.parse(tokenizer, parse_context)
      self
    end

    def registers
      @registers ||= {}
    end

    def assigns
      @assigns ||= {}
    end

    def instance_assigns
      @instance_assigns ||= {}
    end

View on GitHub (pinned to 807d45a6b3)