{"record":{"id":"48afab86df6e4353","repo":"ViewComponent/view_component","slug":"inline-templates-can-only-be-defined-once-per-comp","errorCode":null,"errorMessage":"Inline templates can only be defined once per-component.","messagePattern":"Inline templates can only be defined once per-component\\.","errorType":"exception","errorClass":"ViewComponent::MultipleInlineTemplatesError","httpStatus":null,"severity":"error","filePath":"lib/view_component/inline_template.rb","lineNumber":14,"sourceCode":"# frozen_string_literal: true\n\nmodule ViewComponent # :nodoc:\n  module InlineTemplate\n    extend ActiveSupport::Concern\n\n    Template = Struct.new(:source, :language, :path, :lineno)\n\n    class_methods do\n      def method_missing(method, *args)\n        return super if !method.end_with?(\"_template\")\n\n        if defined?(@__vc_inline_template_defined) && @__vc_inline_template_defined\n          raise MultipleInlineTemplatesError\n        end\n\n        if args.size != 1\n          raise ArgumentError, \"wrong number of arguments (given #{args.size}, expected 1)\"\n        end\n\n        ext = method.to_s.gsub(\"_template\", \"\")\n        template = args.first\n\n        @__vc_inline_template_language = ext\n\n        caller = caller_locations(1..1)[0]\n        @__vc_inline_template = Template.new(\n          template,\n          ext,\n          caller.absolute_path || caller.path,\n          caller.lineno\n        )","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/ViewComponent/view_component/blob/9f22c36fa7d7b44098a8ed97472e3b4674ae420f/lib/view_component/inline_template.rb#L1-L32","documentation":"ViewComponent lets a component define its template inline in Ruby by calling a class-level method ending in _template (erb_template, haml_template, slim_template), intercepted by method_missing in ViewComponent::InlineTemplate. A component renders exactly one template, so a second *_template call on the same class raises ViewComponent::MultipleInlineTemplatesError as soon as the class body is evaluated (at boot or on first autoload). The guard is the per-class @__vc_inline_template_defined flag, so a subclass may define its own inline template but the same class body may not.","triggerScenarios":"Calling two *_template class methods in one component class body, e.g. erb_template followed by haml_template; pasting a new template DSL call without deleting the old one; a copy-pasted component that keeps both the original erb_template and an added slim_template.","commonSituations":"Migrating a component from ERB to Haml/Slim and leaving both calls behind; merging two inline-template components into one; onboarding confusion where devs assume each format needs its own declaration. Because the raise happens during class load, the failure often surfaces first in boot logs or the first request that autoloads the file.","solutions":["Delete one of the *_template calls so the class defines exactly one inline template (check for erb_template, haml_template, slim_template, etc. in the file).","If you were switching template languages, merge the markup into a single call in the new language and remove the old one.","If you intended two variants, split them into two components (or a base class plus a subclass, since subclasses may define their own inline template).","If both formats must coexist for one component, move them to template files (app/components/<name>/*.erb plus variant-aware templates) instead of inline templates."],"exampleFix":"# before\nclass CardComponent < ViewComponent::Base\n  erb_template <<-ERB\n    <div class=\"card\"><%= content %></div>\n  ERB\n\n  haml_template \"%div.card= content\" # second inline template -> MultipleInlineTemplatesError\nend\n\n# after\nclass CardComponent < ViewComponent::Base\n  erb_template <<-ERB\n    <div class=\"card\"><%= content %></div>\n  ERB\nend","handlingStrategy":"validation","validationCode":"# Before adding an inline template programmatically\nclass CardComponent < ViewComponent::Base; end\n\nraise \"already has an inline template\" unless CardComponent.__vc_inline_template.nil?\nCardComponent.erb_template <<-ERB\n  <div><%= content %></div>\nERB","typeGuard":null,"tryCatchPattern":"begin\n  # component class body with *_template call\nrescue ViewComponent::MultipleInlineTemplatesError\n  Rails.logger.error(\"#{name} defines two inline templates; keeping one\")\n  raise\nend","preventionTips":["Keep exactly one *_template call per component file; make it a review checklist item.","Run a CI lint that greps app/components for files containing two or more _template calls.","When switching template languages, replace the old call in the same commit."],"tags":["view-component","ruby-on-rails","inline-template","ruby","dsl-misuse"],"backgroundTag":"duplicate-definition","analyzedSha":"9f22c36fa7d7b44098a8ed97472e3b4674ae420f","analyzedAt":"2026-08-23T10:20:47.008Z","schemaVersion":2},"datasetVersion":"2026-08-23T13:39:53.451Z"}