{"record":{"id":"185c14525f5cbe84","repo":"ruby-concurrency/concurrent-ruby","slug":"immediateexecutor-is-not-supported","errorCode":null,"errorMessage":"ImmediateExecutor is not supported","messagePattern":"ImmediateExecutor is not supported","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/concurrent-ruby-edge/concurrent/actor.rb","lineNumber":75,"sourceCode":"    # @example by class and name\n    #   Actor.spawn(AdHoc, :ping1) { -> message { message } }\n    #\n    # @example by option hash\n    #   inc2 = Actor.spawn(class:    AdHoc,\n    #                      name:     'increment by 2',\n    #                      args:     [2],\n    #                      executor: Concurrent.global_io_executor) do |increment_by|\n    #     lambda { |number| number + increment_by }\n    #   end\n    #   inc2.ask!(2) # => 4\n    #\n    # @param block for context_class instantiation\n    # @param args see {.to_spawn_options}\n    # @return [Reference] never the actual actor\n    def self.spawn(*args, &block)\n      options = to_spawn_options(*args)\n      if options[:executor] && options[:executor].is_a?(ImmediateExecutor)\n        raise ArgumentError, 'ImmediateExecutor is not supported'\n      end\n      if Actor.current\n        Core.new(options.merge(parent: Actor.current), &block).reference\n      else\n        root.ask([:spawn, options, block]).value!\n      end\n    end\n\n    # as {.spawn} but it'll block until actor is initialized or it'll raise exception on error\n    def self.spawn!(*args, &block)\n      spawn(to_spawn_options(*args).merge(initialized: future = Concurrent::Promises.resolvable_future), &block).tap { future.wait! }\n    end\n\n    # @overload to_spawn_options(context_class, name, *args)\n    #   @param [AbstractContext] context_class to be spawned\n    #   @param [String, Symbol] name of the instance, it's used to generate the\n    #     {Core#path} of the actor\n    #   @param args for context_class instantiation","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/ruby-concurrency/concurrent-ruby/blob/0b88d5ff75f69b3740c8f0868e76f833cb2fd45d/lib/concurrent-ruby-edge/concurrent/actor.rb#L57-L93","documentation":"In the concurrent-ruby-edge actor library, Actor.spawn explicitly rejects ImmediateExecutor with ArgumentError. Actors depend on messages being processed asynchronously on an executor; ImmediateExecutor runs tasks inline on the caller thread, which would break actor isolation and deadlock the mailbox dispatch, so the library refuses it up front instead of failing obscurely later.","triggerScenarios":"Concurrent::Actor.spawn(executor: Concurrent::ImmediateExecutor.new) { ... } or the equivalent spawn! / to_spawn_options hash carrying :executor; sharing one executor configuration between promises code (where ImmediateExecutor is legal) and actor code.","commonSituations":"Test suites that globally substitute ImmediateExecutor for determinism and then spawn actors through the same config; performance tuning that tries to eliminate thread hops for lightweight actors; copy-pasting executor setup from promise pipelines into actor spawning.","solutions":["Drop the :executor option and let actors default to Concurrent.global_io_executor","Use a real pool for actors: executor: Concurrent.new_io_executor(:my_actors) or any ThreadPoolExecutor / Concurrent.global_fast_executor","Keep ImmediateExecutor usage scoped to non-actor code paths, and assert executor type in a spec before spawning"],"exampleFix":"# before\nConcurrent::Actor.spawn(executor: Concurrent::ImmediateExecutor.new, args: [1]) { |i| i }\n# ArgumentError: ImmediateExecutor is not supported\n\n# after\nConcurrent::Actor.spawn(executor: Concurrent.global_io_executor, args: [1]) { |i| i }\n\n# or simply omit it\nConcurrent::Actor.spawn(args: [1]) { |i| i }","handlingStrategy":"validation","validationCode":"if executor.is_a?(Concurrent::ImmediateExecutor)\n  raise ArgumentError, 'ImmediateExecutor cannot back actors; use a thread pool'\nend\nConcurrent::Actor.spawn(executor: executor || Concurrent.global_io_executor, &context)","typeGuard":"def actor_safe_executor?(exec)\n  !exec.is_a?(Concurrent::ImmediateExecutor)\nend","tryCatchPattern":"begin\n  Concurrent::Actor.spawn(spawn_opts, &context)\nrescue ArgumentError => e\n  raise unless e.message == 'ImmediateExecutor is not supported'\n  Concurrent::Actor.spawn(spawn_opts.except(:executor), &context) # fall back to default pool\nend","preventionTips":["Never share executor configuration between promises/tests and actor spawning","Let actors default to global_io_executor unless profiling justifies a custom pool","Assert executor type in a helper used by all spawn sites so misconfiguration fails early"],"tags":["ruby","concurrency","actor","executor","argument-error","concurrent-ruby-edge"],"backgroundTag":"invalid-executor-configuration","analyzedSha":"0b88d5ff75f69b3740c8f0868e76f833cb2fd45d","analyzedAt":"2026-08-21T20:12:56.291Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}