{"record":{"id":"de40e83a4031328e","repo":"Shopify/liquid","slug":"undefined-method-method","errorCode":null,"errorMessage":"undefined method #{method}","messagePattern":"undefined method #(.+?)","errorType":"exception","errorClass":"Liquid::UndefinedDropMethod","httpStatus":null,"severity":"error","filePath":"lib/liquid/drop.rb","lineNumber":35,"sourceCode":"  #     end\n  #   end\n  #\n  #   tmpl = Liquid::Template.parse( ' {% for product in product.top_sales %} {{ product.name }} {%endfor%} '  )\n  #   tmpl.render('product' => ProductDrop.new ) # will invoke top_sales query.\n  #\n  # Your drop can either implement the methods sans any parameters\n  # or implement the liquid_method_missing(name) method which is a catch all.\n  class Drop\n    attr_writer :context\n\n    def initialize\n      @context = nil\n    end\n\n    # Catch all for the method\n    def liquid_method_missing(method)\n      return unless @context&.strict_variables\n      raise Liquid::UndefinedDropMethod, \"undefined method #{method}\"\n    end\n\n    # called by liquid to invoke a drop\n    def invoke_drop(method_or_key)\n      if self.class.invokable?(method_or_key)\n        send(method_or_key)\n      else\n        liquid_method_missing(method_or_key)\n      end\n    end\n\n    def key?(_name)\n      true\n    end\n\n    def inspect\n      self.class.to_s\n    end","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/Shopify/liquid/blob/807d45a6b3d4568e64e86b375e3702df2c7c860c/lib/liquid/drop.rb#L17-L53","documentation":"Drop#liquid_method_missing raises Liquid::UndefinedDropMethod when a template invokes a method not defined/invokable on the Drop and strict_variables is enabled. Without strict_variables the miss silently returns nil; with it, Liquid surfaces the missing method as an error so typos are caught.","triggerScenarios":"Rendering with context.strict_variables = true (or Template.render(..., strict_variables: true)) while the template calls a property/method on a Drop that is neither defined on the class nor in its invokable set.","commonSituations":"Typo in a template field name on a drop-backed object; refactoring a drop class and removing a method still referenced by templates; enabling strict_variables in tests after developing with lenient nils.","solutions":["Fix the template to use an existing method/property on the drop.","Add the missing method (or handle it in liquid_method_missing) on the drop class.","If nil is acceptable, disable strict_variables for that render.","Inspect self.class.invokable? to confirm which methods are exposed to templates."],"exampleFix":"// before\nclass ProductDrop < Liquid::Drop\n  def title; @product.title; end\nend\n// after\nclass ProductDrop < Liquid::Drop\n  def title; @product.title; end\n  def price; @product.price; end  # template uses {{ product.price }}\nend","handlingStrategy":"type-guard","validationCode":"def drop_exposes?(drop, method)\n  drop.class.invokable?(method.to_sym)\nend","typeGuard":"def safe_template_fields(drop_class)\n  drop_class.instance_methods(false) # fields templates may reference\nend","tryCatchPattern":"begin\n  tpl.render(ctx, strict_variables: true)\nrescue Liquid::UndefinedDropMethod => e\n  logger.warn(\"Template referenced missing drop method: #{e.message}\")\n  tpl.render(ctx) # lenient re-render if nils acceptable\nend","preventionTips":["Run template test suites with strict_variables: true to catch typos.","Keep drop methods and template fields in sync when refactoring.","Document each drop's exposed interface.","Prefer defining explicit methods over relying on method_missing."],"tags":["ruby","liquid","drop","strict-variables","undefined-method"],"backgroundTag":"method-not-implemented","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"}