Fix Importmap::Engine::Error: Could not find javascript module 'controllers/hello_controller' in importmap in Rails
This error occurs when importmap-rails cannot resolve a JavaScript module referenced in your code. The module is not pinned in config/importmap.rb or the file path does not match the pin name. Add the missing pin to your importmap configuration or verify the file exists at the expected path under app/javascript.
Reading the Stack Trace
Here's what each line means:
- importmap-rails (2.0.1) lib/importmap/map.rb:55:in `resolve': The importmap resolver cannot find the module in its pin registry.
- importmap-rails (2.0.1) lib/importmap/map.rb:32:in `to_json': Importmap is generating the JSON module map for the browser when it encounters the missing module.
- app/views/layouts/application.html.erb:12:in `_app_views_layouts_application_html_erb__render': The layout template includes the importmap tag which triggers the resolution.
Common Causes
1. Module not pinned in importmap.rb
The JavaScript module file exists but is not registered in config/importmap.rb.
# config/importmap.rb
pin 'application', preload: true
# Missing: pin_all_from 'app/javascript/controllers', under: 'controllers'
2. File path does not match pin
The pin name does not match the file location on disk.
# config/importmap.rb
pin 'controllers/hello_controller'
# But file is at app/javascript/controllers/hello-controller.js (hyphen vs underscore)
3. Missing vendor module pin
A third-party library imported in JavaScript is not pinned from a CDN or vendor directory.
// app/javascript/application.js
import 'lodash' // Not pinned in importmap.rb
The Fix
Use pin_all_from to automatically pin all JavaScript files in the controllers directory. This maps every file in app/javascript/controllers to a module name under the controllers namespace, so Stimulus controllers are automatically discoverable.
# config/importmap.rb
pin 'application', preload: true
# No controller pins defined
# config/importmap.rb
pin 'application', preload: true
pin '@hotwired/turbo-rails', to: 'turbo.min.js', preload: true
pin '@hotwired/stimulus', to: 'stimulus.min.js', preload: true
pin_all_from 'app/javascript/controllers', under: 'controllers'
Testing the Fix
require 'rails_helper'
RSpec.describe 'Importmap configuration', type: :request do
it 'renders the layout without importmap errors' do
get root_path
expect(response).to have_http_status(:ok)
end
it 'includes importmap script tag' do
get root_path
expect(response.body).to include('importmap')
end
it 'resolves all pinned modules' do
importmap = Rails.application.importmap
expect { importmap.to_json(resolver: ActionController::Base.helpers) }.not_to raise_error
end
end
Run your tests:
bundle exec rspec spec/requests/importmap_spec.rb
Pushing Through CI/CD
git checkout -b fix/rails-importmap-module,git add config/importmap.rb,git commit -m "fix: pin all stimulus controllers in importmap configuration",git push origin fix/rails-importmap-module
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)
- Update config/importmap.rb with the correct pins.
- Verify all JavaScript modules resolve with bin/importmap audit.
- Run the test suite.
- Open a pull request.
- Merge and verify JavaScript loads correctly 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.
Importmap is simpler and does not require a build step. Use jsbundling-rails with esbuild if you need npm packages, TypeScript, or JSX compilation.
Use bin/importmap pin package-name to pin it from jspm.io CDN, or download it to vendor/javascript and pin it locally.