flippercloud/flipper · error · RuntimeError
Template does not exist: #{path}
Error message
Template does not exist: #{path} What it means
Flipper::UI actions render ERB templates from the gem's views directory (views_path defaults to Flipper::UI.root/views); the private view(name) helper raises unless views_path.join("#{name}.erb") exists, then evaluates it with Erubi (lib/flipper/ui/action.rb:218-223). The raise means the action asked for a template that is not on disk at the exact path printed — almost always a custom action subclass referencing a view that was never created, or a broken/partial flipper-ui gem install missing the views directory.
Source
Thrown at lib/flipper/ui/action.rb:220
def active?
@href.nil?
end
end
# Private
def view_with_layout(&block)
view :layout, &block
end
# Private
def view_without_layout(name)
view name
end
# Private
def view(name)
path = views_path.join("#{name}.erb")
raise "Template does not exist: #{path}" unless path.exist?
eval(Erubi::Engine.new(path.read, escape: true).src)
end
# Internal: The path the app is mounted at.
def script_name
request.env['SCRIPT_NAME']
end
# Internal: Generate urls relative to the app's script name.
#
# url_for("feature") # => "http://localhost:9292/flipper/feature"
# url_for("/thing") # => "http://localhost:9292/thing"
# url_for("https://example.com") # => "https://example.com"
#
def url_for(*parts)
URI.join(request.base_url, script_name + '/', *parts).to_s
endView on GitHub (pinned to 1f86de3ec9)
Solutions
- Create the .erb file at the exact path shown in the error message (it is the absolute path the adapter checked).
- Verify where UI looks: puts Flipper::UI::Action.views_path — then ensure that directory contains <name>.erb; for custom actions, keep the template next to the built-ins or adjust views_path before the first render.
- If built-in pages raise, reinstall/align the flipper-ui gem (gem contents flipper-ui | grep views) so the shipped templates match the action code.
- Boot script/server and hit the route to confirm the template resolves.
Example fix
# before: custom action renders a view that was never created
class GateRollout < Flipper::UI::Action
route %r{\A/gate_rollout\z}
def get
view_response :gate_rollout # raises 'Template does not exist: .../views/gate_rollout.erb'
end
end
# after: create the template the error points to
# file: <views_path>/gate_rollout.erb
# <h1>Gate Rollout</h1>
# <% @features.each do |feature| %>
# <div><%= feature.key %></div>
# <% end %> Defensive patterns
Strategy: validation
Validate before calling
def render_view(action, name)
path = Flipper::UI::Action.views_path.join("#{name}.erb")
raise ArgumentError, "missing template: #{path}" unless path.exist?
action.view_response(name)
end Type guard
def template_exists?(name)
Flipper::UI::Action.views_path.join("#{name}.erb").exist?
end Prevention
- Add a CI spec that boots every custom action and asserts its view_response names have matching .erb files.
- Keep view names and template filenames identical (gate_rollout -> gate_rollout.erb).
- After upgrading or vendoring flipper-ui, verify the gem ships lib/flipper/ui/views (gem contents flipper-ui).
- Smoke-test the mounted UI with script/server after changes to actions or templates.
When it happens
Trigger: A Flipper::UI::Action subclass registered with self.route whose request method calls view_response(:name) or view(:name) with no matching views/<name>.erb under Flipper::UI.root/views; or rendering a built-in action against a flipper-ui installation whose lib/flipper/ui/views directory is missing/renamed (bad gem build, partial git checkout, vendored copy).
Common situations: Writing custom UI actions for a mounted Flipper::UI and forgetting the template; renaming a template file without updating view_response calls; vendoring or forking flipper-ui and not copying the views directory; installing the gem from a git ref that excludes views.
Related errors
- Group #{name.inspect} has already been registered
- Your database needs to be migrated to use the latest Flipper
- Actor limit of #{@limit} exceeded for feature #{feature.key}
- Failed with status: #{response.code}
- #{data_type} is not supported by this adapter
AI-assisted analysis of flippercloud/flipper@1f86de3ec9 (2026-08-23).
Data as JSON: /api/errors/891d436b2fc20110.
Report an issue: GitHub.