{"record":{"id":"945187b43c1bfc17","repo":"puppetlabs/puppet","slug":"call-all-tags-instead","errorCode":null,"errorMessage":"Call 'all_tags' instead.","messagePattern":"Call 'all_tags' instead\\.","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"lib/puppet/parser/templatewrapper.rb","lineNumber":55,"sourceCode":"  end\n  private :script_line\n\n  # Should return true if a variable is defined, false if it is not\n  # @api public\n  def has_variable?(name)\n    scope.include?(name.to_s)\n  end\n\n  # @return [Array<String>] The list of defined classes\n  # @api public\n  def classes\n    scope.catalog.classes\n  end\n\n  # @return [Array<String>] The tags defined in the current scope\n  # @api public\n  def tags\n    raise NotImplementedError, \"Call 'all_tags' instead.\"\n  end\n\n  # @return [Array<String>] All the defined tags\n  # @api public\n  def all_tags\n    scope.catalog.tags\n  end\n\n  # @api private\n  def file=(filename)\n    @__file__ = Puppet::Parser::Files.find_template(filename, scope.compiler.environment)\n    unless @__file__\n      raise Puppet::ParseError, _(\"Could not find template '%{filename}'\") % { filename: filename }\n    end\n  end\n\n  # @api private\n  def result(string = nil)","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/parser/templatewrapper.rb#L37-L73","documentation":"TemplateWrapper#tags intentionally raises NotImplementedError. In old Puppet versions ERB templates could call `tags` to get the current scope's tags; that was removed, and the method now exists only to point callers at all_tags, which returns scope.catalog.tags. Because it raises during template rendering, it aborts the catalog compile of whichever template invoked it.","triggerScenarios":"An ERB template containing `<%= tags %>` or `<% tags.each do |t| %>` rendered via `template('mod/name.erb')` or inline_template. The wrapper binds its methods into the template's binding, so the call dispatches to TemplateWrapper#tags and raises immediately.","commonSituations":"Templates written for Puppet 2.x/early 3.x reused in modern Puppet; copy-pasting old blog examples that gate sections on tags; modules not updated after the tags API change (the NotImplementedError pointer was added to make migration discoverable).","solutions":["Replace `tags` with `all_tags` in the template: `<%= all_tags.inspect %>`.","If you needed per-scope behavior, derive it from scope variables or pass data into the template explicitly instead.","Lock the module to a Puppet version matching its templates, or patch and upstream a fix to the module."],"exampleFix":"# before (mod/templates/motd.erb)\n<% if tags.include?('web') %>Web node<% end %>\n\n# after\n<% if all_tags.include?('web') %>Web node<% end %>","handlingStrategy":"validation","validationCode":"# Grep templates for removed API before upgrade:\n#   rg \"<%[^>]*\\btags\\b\" modules/*/templates/\n# Anything found must switch to all_tags.","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use all_tags in ERB templates; 'tags' has been gone since early Puppet.","Add a CI grep/lint step for removed template APIs when upgrading Puppet or vendored modules.","Prefer EPP templates (Puppet DSL) for new code — they use @all_tags and stay in the supported surface."],"tags":["puppet","erb","templates","deprecated-api","tags"],"backgroundTag":"removed-method-migration","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}