{"record":{"id":"9355cbd8f6664a04","repo":"ruby/ruby","slug":"29-9355cb","errorCode":"29","errorMessage":"Undefined local variable or method `#{name}' for Gemfile","messagePattern":"Undefined local variable or method `#(.+?)' for Gemfile","errorType":"exception","errorClass":"Bundler::Plugin::PluginGemfileError","httpStatus":null,"severity":"error","filePath":"lib/bundler/plugin/dsl.rb","lineNumber":34,"sourceCode":"      #\n      # When we encounter :type attribute with a source block, we add a plugin\n      # by name bundler-source-<type> to list of plugins to be installed.\n      #\n      # These plugins are optional and are not installed when there is conflict\n      # with any other plugin.\n      attr_reader :inferred_plugins\n\n      def initialize\n        super\n        @inferred_plugins = [] # The source plugins inferred from :type\n      end\n\n      def gem(*args)\n        # Ignore regular dependencies when doing the plugins-only pre-parse\n      end\n\n      def method_missing(name, *args)\n        raise PluginGemfileError, \"Undefined local variable or method `#{name}' for Gemfile\" unless Bundler::Dsl.method_defined? name\n      end\n\n      def source(source, *args, &blk)\n        options = args.last.is_a?(Hash) ? args.pop.dup : {}\n        options = normalize_hash(options)\n        return super unless options.key?(\"type\")\n\n        plugin_name = \"bundler-source-#{options[\"type\"]}\"\n\n        return if @dependencies.any? {|d| d.name == plugin_name }\n\n        plugin(plugin_name)\n        @inferred_plugins << plugin_name\n      end\n    end\n  end\nend\n","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/ruby/ruby/blob/0e5b888e1c355f3f728f2659f085820937dada48/lib/bundler/plugin/dsl.rb#L16-L52","documentation":"Plugin::Dsl pre-parses the Gemfile to collect source plugins while ignoring regular `gem` calls; its method_missing accepts a name only if Bundler::Dsl defines that method (method_defined? check), otherwise it raises PluginGemfileError 'Undefined local variable or method `<name>' for Gemfile'. Only standard Gemfile DSL verbs survive the plugins pre-parse.","triggerScenarios":"The Gemfile calls a helper or extension that Bundler::Dsl does not define - e.g. a leftover `env :production do`, a custom `github \"...\"` helper macro, `system \"...\"`, or a typo'd keyword - and plugin evaluation runs over the file.","commonSituations":"Gemfiles that rely on application-level helpers or metaprogramming defined outside the file; copying Gemfile snippets from older setups with DSL extensions; enabling the plugins feature (BUNDLE_PLUGINS / `bundle plugin`) makes the strict pre-parse run where it previously didn't.","solutions":["Rewrite the offending call with standard DSL: `gem`, `source`, `group`, `platforms`, `env` only if defined by Dsl, etc.","Define helper methods inside the Gemfile itself (before first use) so they resolve as instance methods during evaluation.","Run `bundle install` - the normal (non-plugin) Dsl error message will point at the same line with better context.","If the construct came from a plugin that provided DSL extensions, ensure that plugin is actually installed/enabled before its syntax is used."],"exampleFix":"# Gemfile\n# before - helper the plugin pre-parse doesn't know\nenv :production do\n  gem \"newrelic_rpm\"\nend\n\n# after - standard DSL\ngroup :production do\n  gem \"newrelic_rpm\"\nend","handlingStrategy":"type-guard","validationCode":"# scan the Gemfile for calls the plugin pre-parse will reject\nsource = File.read(\"Gemfile\")\ncalls = source.scan(/^\\s*([a-z_][a-zA-Z0-9_?!]*)[\\s(]/).flatten.uniq\nstandard = %w[source gem group platforms plugin git path env_if ruby install_if\ngemspec eval_gemfile path! git! source!] \nunknown = calls - standard - Bundler::Dsl.instance_methods.map(&:to_s)\nabort \"non-DSL calls in Gemfile: #{unknown.join(', ')}\" unless unknown.empty?","typeGuard":"# guard used by the plugin Dsl itself - reuse it before evaluating a Gemfile\nknown_to_dsl = ->(name) { Bundler::Dsl.method_defined?(name) }\n\n%w[github env custom_helper].each do |candidate|\n  warn \"#{candidate} will raise PluginGemfileError\" unless known_to_dsl[candidate.to_sym]\nend","tryCatchPattern":"begin\n  Bundler::Plugin.eval_gemfile(gemfile_path)\nrescue Bundler::Plugin::PluginGemfileError => e\n  name = e.message[/method `(\\S+)' for Gemfile/, 1]\n  abort \"replace #{name} with standard Gemfile DSL (gem/source/group/platforms)\"\nend","preventionTips":["Use only Bundler's standard DSL verbs in Gemfiles that will be parsed for plugins.","Define custom helpers inside the Gemfile before calling them so they resolve as methods.","When enabling plugins (bundle plugin install), immediately run bundle install to surface strict-parse errors early."],"tags":["bundler","plugin","gemfile","dsl","undefined-method"],"backgroundTag":"undefined-method-invocation","analyzedSha":"0e5b888e1c355f3f728f2659f085820937dada48","analyzedAt":"2026-08-21T14:25:43.473Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}