puma/puma · error · ArgumentError
workers must be an Integer or :auto
Error message
workers must be an Integer or :auto
What it means
ArgumentError from Puma::Configuration#parse_workers (lib/puma/configuration.rb:450): worker counts must be an Integer, an integer-like string, or 'auto'/:auto (which resolves to Concurrent.available_processor_count). Anything Integer() cannot coerce — '2.5', 'two', ' ', or a wrong-typed value — is re-raised with this message. It flows from the workers DSL (lib/puma/dsl.rb:739) and from the WEB_CONCURRENCY environment variable read at lib/puma/configuration.rb:250.
Source
Thrown at lib/puma/configuration.rb:450
def require_processor_counter
require 'concurrent/utility/processor_counter'
rescue LoadError
warn <<~MESSAGE
WEB_CONCURRENCY=auto or workers(:auto) requires the "concurrent-ruby" gem to be installed.
Please add "concurrent-ruby" to your Gemfile.
MESSAGE
raise
end
def parse_workers(value)
if value == :auto || value == 'auto'
require_processor_counter
Integer(::Concurrent.available_processor_count)
else
Integer(value)
end
rescue ArgumentError, TypeError
raise ArgumentError, "workers must be an Integer or :auto"
end
# Load and use the normal Rack builder if we can, otherwise
# fallback to our minimal version.
def rack_builder
# Load bundler now if we can so that we can pickup rack from
# a Gemfile
if @puma_bundler_pruned
begin
require 'bundler/setup'
rescue LoadError
end
end
begin
require 'rack'
require 'rack/builder'
::Rack::BuilderView on GitHub (pinned to b8341dc946)
Solutions
- Set WEB_CONCURRENCY to a plain integer string ('2') or 'auto'
- In config/puma.rb use workers Integer(workers_count) or workers :auto — never a float or free text
- Inspect the actual value at deploy time: p "WEB_CONCURRENCY=#{ENV['WEB_CONCURRENCY'].inspect}" before starting Puma
- Fix the source (docker-compose env, .env, CI variable) rather than overriding in the config file
Example fix
# docker-compose.yml — before environment: - WEB_CONCURRENCY=two # after environment: - WEB_CONCURRENCY=2
Defensive patterns
Strategy: validation
Validate before calling
# deploy-time guard before booting Puma
if (w = ENV['WEB_CONCURRENCY'])
raise ArgumentError, "WEB_CONCURRENCY must be an integer or 'auto', got #{w.inspect}" unless w.match?(/\A\d+\z|\Aauto\z/)
end Type guard
def valid_workers?(v) = v.nil? || v == :auto || v == 'auto' || (Integer(v) rescue false)
Try / catch
# wrapper starting Puma with a clear failure message
begin
require 'puma/launcher' # or shell out to `bundle exec puma`
rescue ArgumentError => e
abort "puma config/ENV error: #{e.message} (check WEB_CONCURRENCY=#{ENV['WEB_CONCURRENCY'].inspect})"
end Prevention
- Validate WEB_CONCURRENCY in .env samples and CI with a strict /\A(\d+|auto)\z/ regex
- Never store worker counts as floats or with units ('2 workers') in orchestration files
- Print the resolved value (inspect, not to_s) in deploy logs so hidden whitespace/typos are visible
When it happens
Trigger: workers "2.5" or workers :four in config/puma.rb; ENV['WEB_CONCURRENCY'] set to 'two', '2.5', or a stray character via .env, docker-compose, or CI secrets. Note nil is legal for the DSL (means 0), and strings like '2' are fine because Integer('2') works; only 'auto' is special-cased.
Common situations: Typo'd WEB_CONCURRENCY in deployment tooling (Capistrano, Kamal, Heroku config vars); .env files with trailing characters or units ('2 workers'); configs passing a Float; scripts exporting variables with quotes/whitespace corruption.
Related errors
- unsupported IO selector backend: #{backend} (available backe
- A block must be provided to `single`
- A block must be provided to `cluster`
- expected #{options_key} to be given a block
- #{desc} file '#{file}' does not exist
AI-assisted analysis of puma/puma@b8341dc946 (2026-08-21).
Data as JSON: /api/errors/68be2eeffb2a5411.
Report an issue: GitHub.