Shopify/liquid · error · Liquid::UndefinedFilter

undefined filter #

Error message

undefined filter #{method}

What it means

`StrainerTemplate#invoke` raises Liquid::UndefinedFilter when `context.strict_filters` is enabled and a template references a filter that is not registered/invokable. Without strict_filters, unknown filters are no-ops returning the first argument; in strict mode Liquid fails fast to surface typos and missing registrations.

Solutions

  1. Register the missing filter: `Liquid::Template.register_filter(MyFilter)` (or add it to the Environment's filters).
  2. Fix the filter name typo in the template.
  3. Verify the filter is registered on the same environment/template instance that renders the document.
  4. Disable strict_filters if undefined filters should be tolerated (returns the input unchanged).
  5. Run template linting with strict_filters in CI to catch unknown filter usage before production.

Example fix

// before
Liquid::Template.parse(src).render( assigns, strict_filters: true ) # filter never registered
// after
Liquid::Template.register_filter(MyFilter)
Liquid::Template.parse(src).render( assigns, strict_filters: true )
Defensive patterns

Strategy: validation

Validate before calling

# before render (strict mode)
used = src.scan(/\|\s*(\w+)/).flatten
missing = used.uniq - Liquid::StrainerTemplate.send(:filter_methods).to_a
raise "unknown filters: #{missing}" unless missing.empty?

Type guard

def filters_registered?(names)
  names.all? { |n| Liquid::StrainerTemplate.send(:filter_methods).include?(n.to_s) }
end

Try / catch

begin
  template.render(assigns, strict_filters: true)
rescue Liquid::UndefinedFilter => e
  log_and_render_with_fallback
end

Prevention

When it happens

Trigger: Rendering `{{ x | my_custom_filter }}` (or a typo'd built-in) with strict_filters: true while the filter module has not been added via `Liquid::Template.register_filter` or is not in the environment's filter registry.

Common situations: Enabling strict_filters in production after developing without it; custom filters registered on a different Liquid::Environment/Template instance than the one rendering; typos like `upcase` vs `upcase_first`; upgrading Liquid where a filter was renamed or removed.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at lib/liquid/strainer_template.rb:54

        subclass.instance_variable_set(:@filter_methods, @filter_methods.dup)
      end

      def filter_method_names
        filter_methods.map(&:to_s).to_a
      end

      private

      def filter_methods
        @filter_methods ||= Set.new
      end
    end

    def invoke(method, *args)
      if self.class.invokable?(method)
        send(method, *args)
      elsif @context.strict_filters
        raise Liquid::UndefinedFilter, "undefined filter #{method}"
      else
        args.first
      end
    rescue ::ArgumentError => e
      raise Liquid::ArgumentError, e.message, e.backtrace
    end
  end
end

View on GitHub (pinned to 807d45a6b3)