ruby -w: enable Ruby warnings (and -W0, -W2, $VERBOSE)
- tool
- Ruby
- command
- ruby
- flag
- -w, -W[level], -W:category
- default
- -W1: only important warnings; verbose and deprecation warnings are off
ruby -w script.rb runs the script in verbose warning mode: Ruby also prints warnings that are hidden by default, such as unused local variables, method redefinitions, deprecated features and suspicious syntax. -w is the same as -W2 (or -W) and sets $VERBOSE to true. -W0 turns all warnings off, and -W:deprecated / -W:experimental switch individual categories.
Default, -w and -W0
The example runs the official CRuby 3.4 build for WebAssembly from the ruby.wasm project, as a regular command-line program with Node.js; ruby below is that interpreter:
curl -sSfLO https://github.com/ruby/ruby.wasm/releases/download/2.8.1/ruby-3.4-wasm32-unknown-wasip1-full.tar.gz
echo "ccda86a375a4fe09849846d3b03a370172a4902a0c571087f48457388a2762c7 ruby-3.4-wasm32-unknown-wasip1-full.tar.gz" | sha256sum -c --quiet
tar xzf ruby-3.4-wasm32-unknown-wasip1-full.tar.gz
cat > ruby.mjs <<'JS'
// Minimal "ruby" command: runs the official CRuby 3.4 WASI build with the given arguments
import fs from "node:fs";
import { WASI } from "node:wasi";
const root = "ruby-3.4-wasm32-unknown-wasip1-full/usr";
const wasi = new WASI({ version: "preview1", args: ["ruby", "--disable-gems", ...process.argv.slice(2)], env: {}, preopens: { "/usr": root, ".": "." }, returnOnExit: true });
const mod = await WebAssembly.compile(fs.readFileSync(`${root}/local/bin/ruby`));
process.exitCode = wasi.start(await WebAssembly.instantiate(mod, wasi.getImportObject()));
JS
ruby() { node --no-warnings ruby.mjs "$@"; }
cat > app.rb <<'EOF'
def greet(name)
unused = name.upcase
"hello #{name}"
end
def greet(name)
"hi #{name}"
end
warn "explicit warn() call"
puts greet("ruby")
puts "$VERBOSE = #{$VERBOSE.inspect}"
EOF
echo "== default"
ruby app.rb
echo "== -w"
ruby -w app.rb
echo "== -W0"
ruby -W0 app.rbOutput
== default explicit warn() call hi ruby $VERBOSE = false == -w app.rb:2: warning: assigned but unused variable - unused app.rb:6: warning: method redefined; discarding old greet app.rb:1: warning: previous definition of greet was here explicit warn() call hi ruby $VERBOSE = true == -W0 hi ruby $VERBOSE = nil
By default only the explicit warn call appears, and $VERBOSE is false. With -w Ruby also reports the unused variable (found while parsing) and the redefined method (found while running), each with file and line. With -W0 even warn is silent and $VERBOSE is nil.
Levels and categories
| Option | $VERBOSE | Effect |
|---|---|---|
| -W0 | nil | No warnings at all, including Kernel#warn |
| -W1 (default) | false | Important warnings only |
| -W2, -W, -w | true | Verbose warnings plus deprecation warnings |
| -W:deprecated | unchanged | Enable deprecation warnings only |
| -W:no-deprecated | unchanged | Disable deprecation warnings |
| -W:experimental / -W:no-experimental | unchanged | Warnings for experimental features |
| -W:performance | unchanged | Performance warnings (Ruby 3.3+), off by default |
In code the same switches are Warning[:deprecated] = true and $VERBOSE = true. Because -w is processed when Ruby starts, it also covers warnings raised while files are parsed, which a $VERBOSE = true line in the script itself comes too late for.
Using it with tools
RUBYOPT=-w bundle exec rake test # warnings in the whole test run
ruby -wc lib/my_lib.rb # parse-time warnings without running
ruby -W:deprecated app.rb # only deprecations before an upgradeRUBYOPT reaches every Ruby process started by Bundler, Rake and test runners (see bundle exec). Expect warnings from gems as well as from your code; the path in each message tells them apart.
Pitfalls
- Warnings are not errors: the program still runs and exits with status 0. To fail CI on warnings, override
Warning.warnin the test helper and raise, or grep the output. - On Linux,
#!/usr/bin/env ruby -wpassesruby -wtoenvas a single word and fails; use#!/usr/bin/env -S ruby -w, a direct path such as#!/usr/bin/ruby -w, or$VERBOSE = true. - A method redefinition warning often points to a real bug: two files defining the same helper. A call that then fails with wrong number of arguments is a common consequence.
- For a syntax-only check that also shows parse warnings, see ruby -c.
FAQ
How do I turn on Ruby warnings for my test suite?
Run it with RUBYOPT=-w (for example RUBYOPT=-w bundle exec rake test), or set $VERBOSE = true at the top of the test helper. Minitest and RSpec also have their own options to enable warnings.
How do I see deprecation warnings in Ruby 3?
Since Ruby 2.7.2, deprecation warnings are off by default. -w turns them on together with the other verbose warnings; to enable only them, use -W:deprecated or Warning[:deprecated] = true.
How do I silence warnings from a gem?
Run with -W0 or RUBYOPT=-W0 to silence all warnings, or override Warning.warn to filter messages whose path is inside the gem. Prefer updating the gem, because the warnings often announce breaking changes.