Skip to content

/flags/ruby/ruby-w-warnings

ruby -w: enable Ruby warnings (and -W0, -W2, $VERBOSE)

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash)updated
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:

bash
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.rb

Output

== 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$VERBOSEEffect
-W0nilNo warnings at all, including Kernel#warn
-W1 (default)falseImportant warnings only
-W2, -W, -wtrueVerbose warnings plus deprecation warnings
-W:deprecatedunchangedEnable deprecation warnings only
-W:no-deprecatedunchangedDisable deprecation warnings
-W:experimental / -W:no-experimentalunchangedWarnings for experimental features
-W:performanceunchangedPerformance 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

bash
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 upgrade

RUBYOPT 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.warn in the test helper and raise, or grep the output.
  • On Linux, #!/usr/bin/env ruby -w passes ruby -w to env as 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.

Sources