Skip to content

/errors/ruby/wrong-number-of-arguments

Ruby ArgumentError: wrong number of arguments (given 1, expected 0)

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash)updated
tool
Ruby
exit code
1
versions
Ruby 3.x
os
any

ArgumentError: wrong number of arguments (given 1, expected 0) means a method was called with a different number of arguments than its definition accepts: here one argument for a method that takes none. Ruby checks the count on every call. The first line of the backtrace (in 'greet') is the method being called, the next line is the caller. Change the call to match the method, or the method to accept the arguments. Other forms of the message are (given 0, expected 1), (given 3, expected 1..2) for optional arguments and (given 1, expected 0; required keyword: name) for keywords.

Reproduce it

CRuby 3.4 compiled to WebAssembly (ruby.wasm, the official Ruby project build), run with Node.js:

bash
npm init -y >/dev/null
npm install --silent --no-audit --no-fund @ruby/3.4-wasm-wasi@2.8.1 @ruby/wasm-wasi@2.8.1 >/dev/null 2>&1
cat > app.rb <<'EOF'
def greet
  "hi"
end

def connect(host, port = 5432)
  "#{host}:#{port}"
end

def create_user(name:, admin: false)
  "#{name} admin=#{admin}"
end

class Point
  def initialize(x, y)
    @x = x
    @y = y
  end
end

calls = {
  'greet("Ada")'                   => -> { greet("Ada") },
  'connect'                        => -> { connect },
  'connect("db", 5432, "x")'       => -> { connect("db", 5432, "x") },
  'create_user({ name: "Ada" })'   => -> { create_user({ name: "Ada" }) },
  'Point.new(1)'                   => -> { Point.new(1) },
}
calls.each do |code, fn|
  fn.call
rescue ArgumentError => e
  puts "#{code.ljust(30)} #{e.class}: #{e.message}"
end
puts "RUBY_VERSION #{RUBY_VERSION}"
EOF
cat > run.mjs <<'EOF'
import fs from "node:fs/promises";
import { DefaultRubyVM } from "@ruby/wasm-wasi/dist/node";
const wasm = await WebAssembly.compile(await fs.readFile("node_modules/@ruby/3.4-wasm-wasi/dist/ruby+stdlib.wasm"));
const { vm } = await DefaultRubyVM(wasm);
vm.eval(await fs.readFile("app.rb", "utf8") + "\n$stdout.flush");
EOF
node --no-warnings run.mjs

Output

greet("Ada")                   ArgumentError: wrong number of arguments (given 1, expected 0)
connect                        ArgumentError: wrong number of arguments (given 0, expected 1..2)
connect("db", 5432, "x")       ArgumentError: wrong number of arguments (given 3, expected 1..2)
create_user({ name: "Ada" })   ArgumentError: wrong number of arguments (given 1, expected 0; required keyword: name)
Point.new(1)                   ArgumentError: wrong number of arguments (given 1, expected 2)
RUBY_VERSION 3.4.1

Fix it

Make the call match the definition, or make the definition accept what callers pass:

ruby
def greet(name = "world")          # optional argument with a default
  "hi #{name}"
end

def log(message, *tags)            # any number of extra arguments
  puts "[#{tags.join(',')}] #{message}"
end

create_user(name: "Ada")           # pass keywords, not a positional hash
opts = { name: "Ada", admin: true }
create_user(**opts)                # splat a hash into keyword arguments

Ruby 3 keyword arguments

Since Ruby 3.0, a hash passed as the last positional argument is no longer converted into keyword arguments. Code written for Ruby 2.7 that calls create_user({ name: "Ada" }) or create_user(opts) now fails with wrong number of arguments (given 1, expected 0; required keyword: name). Add ** (create_user(**opts)) or write the keywords out.

Sources