Fix ActionController::UnknownFormat: ActionController::UnknownFormat: TurboStreamController#create is missing a template for this request format and target in Rails
This error occurs when a controller action receives a Turbo Stream request but has no corresponding turbo_stream template or respond_to block handling the format. Create a .turbo_stream.erb template or add format.turbo_stream to your respond_to block to handle Turbo Stream requests properly in your Rails controller.
Reading the Stack Trace
Here's what each line means:
- actionpack (7.1.3) lib/action_controller/metal/implicit_render.rb:43:in `default_render': Rails cannot find a template matching the turbo_stream format for this action.
- app/controllers/comments_controller.rb:10:in `create': The create action does not handle the turbo_stream format explicitly.
- turbo-rails (1.5.0) lib/turbo/broadcastable.rb:130:in `broadcast_action': Turbo Rails is trying to broadcast the result but the format is not handled.
Common Causes
1. Missing turbo_stream template
The controller action has no .turbo_stream.erb template file for the action.
# app/controllers/comments_controller.rb
def create
@comment = @post.comments.create!(comment_params)
# No app/views/comments/create.turbo_stream.erb exists
end
2. Missing respond_to block
The controller does not have a respond_to block that handles the turbo_stream format.
def create
@comment = @post.comments.create!(comment_params)
redirect_to @post # Only handles HTML, not turbo_stream
end
3. Turbo Drive submitting as turbo_stream
A form with data-turbo=true submits as turbo_stream format but the controller only handles HTML.
<%= form_with model: [@post, Comment.new] do |f| %>
<%= f.text_area :body %>
<%= f.submit 'Add Comment' %>
<% end %>
<!-- Turbo submits this as turbo_stream by default -->
The Fix
Add a respond_to block that handles both turbo_stream and HTML formats. Create a .turbo_stream.erb template that uses turbo_stream helpers to update the page. The HTML fallback handles non-Turbo requests.
def create
@comment = @post.comments.create!(comment_params)
redirect_to @post
end
def create
@comment = @post.comments.create!(comment_params)
respond_to do |format|
format.turbo_stream
format.html { redirect_to @post }
end
end
# app/views/comments/create.turbo_stream.erb
# <%= turbo_stream.append 'comments', partial: 'comments/comment', locals: { comment: @comment } %>
Testing the Fix
require 'rails_helper'
RSpec.describe CommentsController, type: :request do
let(:post_record) { create(:post) }
describe 'POST /posts/:post_id/comments' do
it 'responds to turbo_stream format' do
post post_comments_path(post_record),
params: { comment: { body: 'Great post!' } },
headers: { 'Accept' => 'text/vnd.turbo-stream.html' }
expect(response).to have_http_status(:ok)
expect(response.media_type).to eq('text/vnd.turbo-stream.html')
end
it 'falls back to HTML redirect' do
post post_comments_path(post_record),
params: { comment: { body: 'Great post!' } }
expect(response).to redirect_to(post_record)
end
end
end
Run your tests:
bundle exec rspec spec/requests/comments_spec.rb
Pushing Through CI/CD
git checkout -b fix/rails-turbo-stream-format,git add app/controllers/comments_controller.rb app/views/comments/create.turbo_stream.erb,git commit -m "fix: handle turbo_stream format in comments controller",git push origin fix/rails-turbo-stream-format
Your CI config should look something like this:
name: CI
on:
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_PASSWORD: postgres
ports: ['5432:5432']
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.3'
bundler-cache: true
- run: bin/rails db:setup
- run: bundle exec rspec
The Full Manual Process: 18 Steps
Here's every step you just went through to fix this one bug:
- Notice the error alert or see it in your monitoring tool
- Open the error dashboard and read the stack trace
- Identify the file and line number from the stack trace
- Open your IDE and navigate to the file
- Read the surrounding code to understand context
- Reproduce the error locally
- Identify the root cause
- Write the fix
- Run the test suite locally
- Fix any failing tests
- Write new tests covering the edge case
- Run the full test suite again
- Create a new git branch
- Commit and push your changes
- Open a pull request
- Wait for code review
- Merge and deploy to production
- Monitor production to confirm the error is resolved
Total time: 30-60 minutes. For one bug.
Or Let bugstack Fix It in Under 2 minutes
Every step above? bugstack does it automatically.
Step 1: Install the SDK
gem install bugstack
Step 2: Initialize
require 'bugstack'
Bugstack.init(api_key: ENV['BUGSTACK_API_KEY'])
Step 3: There is no step 3.
bugstack handles everything from here:
- Captures the stack trace and request context
- Pulls the relevant source files from your GitHub repo
- Analyzes the error and understands the code context
- Generates a minimal, verified fix
- Runs your existing test suite
- Pushes through your CI/CD pipeline
- Deploys to production (or opens a PR for review)
Time from error to fix deployed: Under 2 minutes.
Human involvement: zero.
Try bugstack Free →No credit card. 5-minute setup. Cancel anytime.
Deploying the Fix (Manual Path)
- Create turbo_stream templates for all relevant actions.
- Add respond_to blocks in controllers.
- Test with and without Turbo enabled.
- Open a pull request.
- Merge and verify Turbo Stream updates work in staging.
Frequently Asked Questions
BugStack runs the fix through your existing test suite, generates additional edge-case tests, and validates that no other components are affected before marking it safe to deploy.
BugStack never pushes directly to production. Every fix goes through a pull request with full CI checks, so your team can review it before merging.
Yes, add data-turbo='false' to the form element. This makes it submit as a regular HTML form without Turbo Stream.
Turbo Frames replace content within a frame element. Turbo Streams can append, prepend, replace, or remove content anywhere on the page using target IDs.