ViewComponent/view_component · error · ViewComponent::MultipleInlineTemplatesError
Inline templates can only be defined once per-component.
Error message
Inline templates can only be defined once per-component.
What it means
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.
Source
Thrown at lib/view_component/inline_template.rb:14
# frozen_string_literal: true
module ViewComponent # :nodoc:
module InlineTemplate
extend ActiveSupport::Concern
Template = Struct.new(:source, :language, :path, :lineno)
class_methods do
def method_missing(method, *args)
return super if !method.end_with?("_template")
if defined?(@__vc_inline_template_defined) && @__vc_inline_template_defined
raise MultipleInlineTemplatesError
end
if args.size != 1
raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 1)"
end
ext = method.to_s.gsub("_template", "")
template = args.first
@__vc_inline_template_language = ext
caller = caller_locations(1..1)[0]
@__vc_inline_template = Template.new(
template,
ext,
caller.absolute_path || caller.path,
caller.lineno
)View on GitHub (pinned to 9f22c36fa7)
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.
Example fix
# before
class CardComponent < ViewComponent::Base
erb_template <<-ERB
<div class="card"><%= content %></div>
ERB
haml_template "%div.card= content" # second inline template -> MultipleInlineTemplatesError
end
# after
class CardComponent < ViewComponent::Base
erb_template <<-ERB
<div class="card"><%= content %></div>
ERB
end Defensive patterns
Strategy: validation
Validate before calling
# Before adding an inline template programmatically class CardComponent < ViewComponent::Base; end raise "already has an inline template" unless CardComponent.__vc_inline_template.nil? CardComponent.erb_template <<-ERB <div><%= content %></div> ERB
Try / catch
begin
# component class body with *_template call
rescue ViewComponent::MultipleInlineTemplatesError
Rails.logger.error("#{name} defines two inline templates; keeping one")
raise
end Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- wrong number of arguments (given #{args.size}, expected 1)
- Cannot serialize anonymous component class #{component_class
- #{example} is not a valid preview example
- A preview template for example EXAMPLE doesn't exist. To fi
- Cannot serialize render_later with a block
AI-assisted analysis of ViewComponent/view_component@9f22c36fa7 (2026-08-23).
Data as JSON: /api/errors/48afab86df6e4353.
Report an issue: GitHub.