Fix ArgumentError: wrong number of arguments (given 2, expected 1) in Rails
This error occurs when a Ruby method receives more arguments than its signature allows. In Rails, this commonly happens when calling a model method, callback, or service object with extra parameters it was not designed to accept. Fix it by updating the method signature to accept the correct number of arguments or correcting the call site.
Reading the Stack Trace
Here's what each line means:
- app/services/notification_service.rb:8:in `send_notification': The send_notification method at line 8 expects 1 argument but received 2 from the caller.
- app/controllers/orders_controller.rb:24:in `create': The orders controller create action at line 24 calls send_notification with two arguments.
- wrong number of arguments (given 2, expected 1): Ruby's method dispatch detected a mismatch between the call site (2 args) and the method definition (1 arg).
Common Causes
1. Method signature does not match call site
The method was defined to accept one parameter, but the caller passes two, perhaps after adding a new feature that requires an additional argument.
class NotificationService
def send_notification(user)
Mailer.notify(user).deliver_later
end
end
# Controller:
NotificationService.new.send_notification(user, order) # 2 args, method takes 1
2. Callback method with wrong arity
A Rails callback method is defined with the wrong number of parameters for the callback type.
class Order < ApplicationRecord
before_save :set_total
private
def set_total(order) # Wrong: before_save callbacks receive no arguments
self.total = items.sum(&:price)
end
end
The Fix
Update the method signature to accept both the user and order arguments. This aligns the method definition with the call site so Ruby can dispatch the call correctly.
class NotificationService
def send_notification(user)
Mailer.notify(user).deliver_later
end
end
# Controller:
NotificationService.new.send_notification(user, order)
class NotificationService
def send_notification(user, order)
Mailer.notify(user, order).deliver_later
end
end
# Controller:
NotificationService.new.send_notification(user, order)
Testing the Fix
require 'rails_helper'
RSpec.describe NotificationService do
describe '#send_notification' do
let(:user) { User.create!(name: 'Alice', email: 'alice@example.com') }
let(:order) { Order.create!(user: user, total: 99.99) }
it 'accepts user and order arguments without raising' do
service = NotificationService.new
expect { service.send_notification(user, order) }.not_to raise_error
end
it 'enqueues a notification email' do
service = NotificationService.new
expect {
service.send_notification(user, order)
}.to have_enqueued_mail(Mailer, :notify)
end
end
end
Run your tests:
rspec
Pushing Through CI/CD
git checkout -b fix/argument-error-notification,git add app/services/notification_service.rb spec/services/notification_service_spec.rb,git commit -m "fix: update send_notification to accept user and order arguments",git push origin fix/argument-error-notification
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:15
env:
POSTGRES_DB: test_db
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- uses: actions/setup-ruby@v1
with:
ruby-version: '3.2'
bundler-cache: true
- run: bundle exec rails db:create db:migrate
env:
DATABASE_URL: postgres://postgres:postgres@localhost:5432/test_db
RAILS_ENV: test
- run: bundle exec rspec
env:
DATABASE_URL: postgres://postgres:postgres@localhost:5432/test_db
RAILS_ENV: test
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)
- Run rspec locally to confirm the method accepts the correct arguments.
- Open a pull request with the updated method signature.
- Wait for CI checks to pass on the PR.
- Have a teammate review and approve the PR.
- Merge to main and verify notifications work in staging.
Frequently Asked Questions
BugStack finds all call sites for the method, verifies the argument count matches at each one, and runs the full test suite to confirm no other callers break.
All fixes are submitted as pull requests with CI validation. Your team reviews the method signature changes before merging.
Yes, keyword arguments make the call site more readable and resilient to argument order changes. Consider refactoring to send_notification(user:, order:) for clarity.
Use default parameter values like def send_notification(user, order = nil) or a splat operator def send_notification(user, *args) to accept variable arguments.