{"record":{"id":"0522da902bce66d1","repo":"ruby-concurrency/concurrent-ruby","slug":"interval-type-must-be-either-fixed-delay-or-fixe","errorCode":null,"errorMessage":"interval_type must be either :fixed_delay or :fixed_rate","messagePattern":"interval_type must be either :fixed_delay or :fixed_rate","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/concurrent-ruby/concurrent/timer_task.rb","lineNumber":303,"sourceCode":"    end\n\n    # @!attribute [rw] timeout_interval\n    # @return [Fixnum] Number of seconds the task can run before it is\n    #   considered to have failed.\n    def timeout_interval=(value)\n      warn 'TimerTask timeouts are now ignored as these were not able to be implemented correctly'\n    end\n\n    private :post, :<<\n\n    private\n\n    def ns_initialize(opts, &task)\n      set_deref_options(opts)\n\n      self.execution_interval = opts[:execution] || opts[:execution_interval] || EXECUTION_INTERVAL\n      if opts[:interval_type] && ![FIXED_DELAY, FIXED_RATE].include?(opts[:interval_type])\n        raise ArgumentError.new('interval_type must be either :fixed_delay or :fixed_rate')\n      end\n      if opts[:timeout] || opts[:timeout_interval]\n        warn 'TimeTask timeouts are now ignored as these were not able to be implemented correctly'\n      end\n\n      @run_now = opts[:now] || opts[:run_now]\n      @interval_type = opts[:interval_type] || DEFAULT_INTERVAL_TYPE\n      @task = Concurrent::SafeTaskExecutor.new(task)\n      @executor = opts[:executor] || Concurrent.global_io_executor\n      @running = Concurrent::AtomicBoolean.new(false)\n      @age = Concurrent::AtomicFixnum.new(0)\n      @value = nil\n\n      self.observers = Collection::CopyOnNotifyObserverSet.new\n    end\n\n    # @!visibility private\n    def ns_shutdown_execution","sourceCodeStart":285,"sourceCodeEnd":321,"githubUrl":"https://github.com/ruby-concurrency/concurrent-ruby/blob/0b88d5ff75f69b3740c8f0868e76f833cb2fd45d/lib/concurrent-ruby/concurrent/timer_task.rb#L285-L321","documentation":"TimerTask supports two interval semantics: :fixed_delay (default; interval counted after each run completes) and :fixed_rate (interval counted from run start). The :interval_type option is compared by identity against these two symbols, and any other value — including the strings 'fixed_delay'/'fixed_rate' — raises ArgumentError.","triggerScenarios":"TimerTask.new(interval_type: 'fixed_delay') where the string came from YAML/JSON/ENV; typos like :fixed_interval or :fixedrate; forwarding user input unvalidated.","commonSituations":"Config-driven timer setup where the parser returns strings, not symbols; options copied from documentation written with quotes; version upgrades introducing the option into previously untyped config hashes.","solutions":["Use the exact symbols: interval_type: :fixed_rate","Normalize at the config boundary: interval_type: cfg['interval_type']&.to_sym","Whitelist early: raise ArgumentError, 'bad interval_type' unless %i[fixed_delay fixed_rate].include?(type.to_sym)"],"exampleFix":"# before (string from YAML fails the symbol check)\ntask = Concurrent::TimerTask.new(interval_type: config['interval_type']) { tick }\n\n# after\ntype = config['interval_type'].to_s.to_sym if config['interval_type']\ntype = :fixed_delay unless %i[fixed_delay fixed_rate].include?(type)\ntask = Concurrent::TimerTask.new(interval_type: type) { tick }","handlingStrategy":"validation","validationCode":"VALID_INTERVAL_TYPES = %i[fixed_delay fixed_rate].freeze\ntype = opts[:interval_type]&.to_sym\ntype = nil unless VALID_INTERVAL_TYPES.include?(type)\nConcurrent::TimerTask.new(**opts, interval_type: type).tap { |t| t.execute }","typeGuard":"def valid_interval_type?(v)\n  %i[fixed_delay fixed_rate].include?(v.is_a?(String) ? v.to_sym : v)\nend","tryCatchPattern":null,"preventionTips":["Always pass interval_type as a Symbol, never a String","Normalize with to_sym at the YAML/JSON boundary and whitelist against the two legal values","Document the accepted set next to your config schema so typos fail review"],"tags":["ruby","concurrency","timer-task","argument-error","config-validation"],"backgroundTag":"invalid-config-option","analyzedSha":"0b88d5ff75f69b3740c8f0868e76f833cb2fd45d","analyzedAt":"2026-08-21T20:12:56.291Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}