ViewComponent/view_component · error · ViewComponent::ControllerCalledBeforeRenderError

`#controller` can't be used before rendering, as it depends

Error message

`#controller` can't be used before rendering, as it depends on the view context that only exists once a ViewComponent is passed to the Rails render pipeline.

It's sometimes possible to fix this issue by moving code dependent on `#controller` to a [`#before_render` method](https://viewcomponent.org/api.html#before_render--void).

What it means

Error "`#controller` can't be used before rendering, as it depends on the view context that only exists once a ViewComponent is passed to the Rails render pipeline. It's sometimes possible to fix this issue by moving code dependent on `#controller` to a [`#before_render` method](https://viewcomponent.org/api.html#before_render--void)." thrown in ViewComponent/view_component.

Source

Thrown at lib/view_component/base.rb:316

    # (whose _run allocated a fresh OutputBuffer on the view context), the
    # component's stale @output_buffer would capture from the wrong buffer.
    # Temporarily switching to the view context's buffer keeps both in sync.
    #
    # @private
    def capture(...)
      old_output_buffer = @output_buffer
      @output_buffer = view_context.output_buffer if view_context
      super
    ensure
      @output_buffer = old_output_buffer
    end

    # The current controller. Use sparingly as doing so introduces coupling
    # that inhibits encapsulation & reuse, often making testing difficult.
    #
    # @return [ActionController::Base]
    def controller
      raise ControllerCalledBeforeRenderError if view_context.nil?

      @__vc_controller ||= view_context.controller
    end

    # A proxy through which to access helpers. Use sparingly as doing so introduces
    # coupling that inhibits encapsulation & reuse, often making testing difficult.
    #
    # @return [ActionView::Base]
    def helpers
      raise HelpersCalledBeforeRenderError if view_context.nil?

      # Attempt to re-use the original view_context passed to the first
      # component rendered in the rendering pipeline. This prevents the
      # instantiation of a new view_context via `controller.view_context` which
      # always returns a new instance of the view context class.
      #
      # This allows ivars to remain persisted when using the same helper via
      # `helpers` across multiple components and partials.

View on GitHub (pinned to 9f22c36fa7)

Solutions

  1. Move code that calls `#controller` into a `#before_render` method (or the template), which only runs once the view context exists.
  2. If controller data is needed at initialization time, pass it explicitly into the component's initializer instead of reading it via `#controller`.

When it happens

Trigger: Thrown at lib/view_component/base.rb:316 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of ViewComponent/view_component@9f22c36fa7 (2026-08-23). Data as JSON: /api/errors/38e96c7a33669ec3. Report an issue: GitHub.