ruby-concurrency/concurrent-ruby · error · ArgumentError
unrecognized error mode
Error message
unrecognized error mode
What it means
Concurrent::Agent accepts an :error_mode option choosing failure behavior - :continue (keep processing subsequent actions after an error) or :fail (halt pending actions until restart) - validated against the frozen ERROR_MODES whitelist. Any other value raises ArgumentError at construction time.
Source
Thrown at lib/concurrent-ruby/concurrent/agent.rb:495
# @param [Array<Concurrent::Agent>] agents the Agents on which to wait
# @return [Boolean] true if all actions complete before timeout
#
# @raise [Concurrent::TimeoutError] when timeout is reached
# @!macro agent_await_warning
def await_for!(timeout, *agents)
raise Concurrent::TimeoutError unless await_for(timeout, *agents)
true
end
end
private
def ns_initialize(initial, opts)
@error_mode = opts[:error_mode]
@error_handler = opts[:error_handler]
if @error_mode && !ERROR_MODES.include?(@error_mode)
raise ArgumentError.new('unrecognized error mode')
elsif @error_mode.nil?
@error_mode = @error_handler ? :continue : :fail
end
@error_handler ||= DEFAULT_ERROR_HANDLER
@validator = opts.fetch(:validator, DEFAULT_VALIDATOR)
@current = Concurrent::AtomicReference.new(initial)
@error = Concurrent::AtomicReference.new(nil)
@caller = Concurrent::ThreadLocalVar.new(nil)
@queue = []
self.observers = Collection::CopyOnNotifyObserverSet.new
end
def enqueue_action_job(action, args, executor)
raise ArgumentError.new('no action given') unless action
job = Job.new(action, args, executor, @caller.value || Thread.current.object_id)
synchronize { ns_enqueue_job(job) }View on GitHub (pinned to 0b88d5ff75)
Solutions
- Use one of the two supported symbols: :continue or :fail.
- Validate and default at the edge: raise on unknown config values at load time, symbolize strings with .to_sym once.
- If you need default behavior, omit :error_mode entirely - it defaults to :continue when an :error_handler is given, else :fail.
Example fix
# before agent = Concurrent::Agent.new(0, error_mode: :fail_fast) # after agent = Concurrent::Agent.new(0, error_mode: :fail)
Defensive patterns
Strategy: type-guard
Type guard
ERROR_MODES = %i[continue fail].freeze
def valid_error_mode?(mode)
ERROR_MODES.include?(mode)
end
mode = opts.fetch(:error_mode, :fail)
raise ArgumentError, "error_mode must be one of #{ERROR_MODES}" unless valid_error_mode?(mode)
agent = Concurrent::Agent.new(initial, error_mode: mode) Try / catch
begin
agent = Concurrent::Agent.new(initial, **opts)
rescue ArgumentError => e
raise ConfigError, "bad agent options: #{e.message}"
end Prevention
- Only :continue and :fail exist - :continue keeps processing after action errors, :fail halts until restart.
- Symbolize config strings once (.to_sym) and validate against a whitelist at load time.
- Omit :error_mode to get the default (:continue with an :error_handler, else :fail).
When it happens
Trigger: Concurrent::Agent.new(0, error_mode: :fail_fast), :continue_on_error, :raise, :ignore, or the string 'continue' (strings do not match the symbol whitelist).
Common situations: Guessing Clojure-flavored or custom names for the mode; reading the mode from config/ENV without symbolizing or validating; copying agent setup between projects or versions where expected option names differ.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- invalid action
- no action given
- unbuffered channels cannot have a capacity
- capacity must be at least 1 for this buffer type
- no block given
AI-assisted analysis of ruby-concurrency/concurrent-ruby@0b88d5ff75 (2026-08-21).
Data as JSON: /api/errors/7e44ec1d2e1d99d4.
Report an issue: GitHub.