Shopify/liquid · error · ArgumentError

Expected Hash or Liquid::Context as parameter

Error message

Expected Hash or Liquid::Context as parameter

What it means

Template#render accepts an optional first argument that must be a Hash of assigns, a Liquid::Context, or nil. Any other type (String, Array, integer, etc.) raises ArgumentError with 'Expected Hash or Liquid::Context as parameter'.

Solutions

  1. Convert the argument to a Hash before rendering: template.render(JSON.parse(json)).
  2. Pass variables inside a Hash: template.render('key' => value) or use template.assignments/instance assigns.
  3. If sharing state across renders, construct and pass a Liquid::Context explicitly.
  4. Pass nothing (or nil) when no outer assigns are needed.

Example fix

// before
template.render('{"user": "bob"}')
// after
template.render(JSON.parse('{"user": "bob"}'))
Defensive patterns

Strategy: type-guard

Validate before calling

raise ArgumentError, 'assigns must be a Hash' unless arg.nil? || arg.is_a?(Hash) || arg.is_a?(Liquid::Context)

Type guard

def valid_render_arg?(arg)
  arg.nil? || arg.is_a?(Hash) || arg.is_a?(Liquid::Context)
end

Try / catch

begin
  template.render(assigns)
rescue ArgumentError => e
  raise e unless e.message.include?('Expected Hash or Liquid::Context')
  template.render(assigns.to_h)
end

Prevention

When it happens

Trigger: Calling template.render('foo'), template.render(assigns_array), or template.render(some_object) where the first argument is neither Hash, Liquid::Context, nor omitted/nil.

Common situations: Passing a JSON string of variables instead of a parsed Hash; passing OpenStruct/dry structs as assigns; refactoring from render! to render while changing argument shapes; tests (e.g. test_internal_error_is_raised_with_template_name) exercising bad arguments.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at lib/liquid/template.rb:163

      when Liquid::Context
        c = args.shift

        if @rethrow_errors
          c.exception_renderer = Liquid::RAISE_EXCEPTION_LAMBDA
        end

        c
      when Liquid::Drop
        drop = args.shift
        c    = Context.new([drop, assigns], instance_assigns, registers, @rethrow_errors, @resource_limits, {}, @environment)
        drop.context = c if drop.respond_to?(:context=)
        c
      when Hash
        Context.new([args.shift, assigns], instance_assigns, registers, @rethrow_errors, @resource_limits, {}, @environment)
      when nil
        Context.new(assigns, instance_assigns, registers, @rethrow_errors, @resource_limits, {}, @environment)
      else
        raise ArgumentError, "Expected Hash or Liquid::Context as parameter"
      end

      output = nil

      case args.last
      when Hash
        options = args.pop
        output  = options[:output] if options[:output]
        static_registers = context.registers.static

        options[:registers]&.each do |key, register|
          static_registers[key] = register
        end

        apply_options_to_context(context, options)
      when Module, Array
        context.add_filters(args.pop)
      end

View on GitHub (pinned to 807d45a6b3)