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
- Register the missing filter: `Liquid::Template.register_filter(MyFilter)` (or add it to the Environment's filters).
- Fix the filter name typo in the template.
- Verify the filter is registered on the same environment/template instance that renders the document.
- Disable strict_filters if undefined filters should be tolerated (returns the input unchanged).
- 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
- Register every custom filter on the same environment used for rendering
- Enable strict_filters in CI linting to catch typos early
- Keep a documented registry of available filters for template authors
- Re-audit filter names after Liquid version upgrades
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
- e.message (re-raised as Liquid::ZeroDivisionError from…
- e.message (re-raised as Liquid::ZeroDivisionError from…
- e.message (re-raised as Liquid::FloatDomainError from…
- e.message (re-raised as Liquid::FloatDomainError from…
- e.message (re-raised as Liquid::FloatDomainError from…
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)