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
      end

View on GitHub (pinned to 1f86de3ec9)

Solutions

  1. Create the .erb file at the exact path shown in the error message (it is the absolute path the adapter checked).
  2. 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.
  3. 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.
  4. 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

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


AI-assisted analysis of flippercloud/flipper@1f86de3ec9 (2026-08-23). Data as JSON: /api/errors/891d436b2fc20110. Report an issue: GitHub.