javan/whenever · error · ArgumentError

You cannot specify an ':at' when using the shortcuts for tim

Error message

You cannot specify an ':at' when using the shortcuts for times.

What it means

Whenever maps the cron @ keywords (:reboot, :yearly, :annually, :monthly, :weekly, :daily, :midnight, :hourly) directly to raw @-syntax cron like @daily, which has no minute or hour field. Because there is nowhere to place a time of day, parse_symbol raises ArgumentError when :at is also given (any Chronic-parsed string yields a Time, and a numeric greater than 0 also triggers it). The interval symbols (:year, :month, :week, :day, :hour, :minute) are converted to seconds first and DO accept :at.

Source

Thrown at lib/whenever/cron.rb:80

      end

      def parse_symbol
        shortcut = case @time
          when *KEYWORDS then "@#{@time}" # :reboot => '@reboot'
          when :year     then Whenever.seconds(1, :year)
          when :day      then Whenever.seconds(1, :day)
          when :month    then Whenever.seconds(1, :month)
          when :week     then Whenever.seconds(1, :week)
          when :hour     then Whenever.seconds(1, :hour)
          when :minute   then Whenever.seconds(1, :minute)
        end

        if shortcut.is_a?(Numeric)
          @time = shortcut
          parse_time
        elsif shortcut
          if @at.is_a?(Time) || (@at.is_a?(Numeric) && @at > 0)
            raise ArgumentError, "You cannot specify an ':at' when using the shortcuts for times."
          else
            return shortcut
          end
        else
          parse_as_string
        end
      end

      def parse_time
        timing = Array.new(5, '*')
        case @time
          when Whenever.seconds(0, :seconds)...Whenever.seconds(1, :minute)
            raise ArgumentError, "Time must be in minutes or higher"
          when Whenever.seconds(1, :minute)...Whenever.seconds(1, :hour)
            minute_frequency = @time / 60
            timing[0] = comma_separated_timing(minute_frequency, 59, @at || 0)
          when Whenever.seconds(1, :hour)...Whenever.seconds(1, :day)
            hour_frequency = (@time / 60 / 60).round

View on GitHub (pinned to 756163ed1a)

Solutions

  1. Replace the keyword with an interval: every 1.day, at: '4pm' (or the equivalent symbols :day, :hour, :week, :month, :year).
  2. Drop the :at option and accept the @-shortcut's fixed cron time (e.g. @daily runs at midnight).
  3. Use raw cron syntax for full control: every '0 16 * * *' for 4pm daily.
  4. If generating schedules programmatically, check Whenever::Output::Cron::KEYWORDS before attaching :at.

Example fix

# before
every :daily, at: '4:30pm' do
  rake 'logs:clear'
end

# after
every 1.day, at: '4:30pm' do
  rake 'logs:clear'
end
Defensive patterns

Strategy: validation

Validate before calling

AT_KEYWORDS = %i[reboot yearly annually monthly weekly daily midnight hourly]
if AT_KEYWORDS.include?(frequency) && options.key?(:at)
  abort('at: cannot be combined with the ' + frequency.inspect + ' shortcut; use an interval such as 1.day instead')
end
every frequency, options

Type guard

def accepts_at?(time)
  !%i[reboot yearly annually monthly weekly daily midnight hourly].include?(time)
end

Try / catch

begin
  Whenever.cron(file: 'config/schedule.rb')
rescue ArgumentError => e
  abort('config/schedule.rb invalid: ' + e.message)
end

Prevention

When it happens

Trigger: every :daily, at: '4pm'; every :hourly, at: 30; every :midnight, at: '3:00am' — any symbol in Whenever::Output::Cron::KEYWORDS combined with a truthy :at. Contrast: every :day, at: '4pm' does NOT raise, because :day becomes 86400 seconds and goes through parse_time. A string :at is Chronic-parsed in the constructor, so even '00:00' becomes a Time and triggers the raise.

Common situations: Developers with a cron background writing every :daily, at: ... since @daily is familiar syntax; refactoring every 1.day, at: ... to the shorter :daily and keeping the :at option; copy-pasting examples that mix @ keywords with :at; schedule generators that attach :at unconditionally to every job.

Related errors


AI-assisted analysis of javan/whenever@756163ed1a (2026-08-21). Data as JSON: /api/errors/860e63ddea877a44. Report an issue: GitHub.