{"record":{"id":"860e63ddea877a44","repo":"javan/whenever","slug":"you-cannot-specify-an-at-when-using-the-shortcu","errorCode":null,"errorMessage":"You cannot specify an ':at' when using the shortcuts for times.","messagePattern":"You cannot specify an ':at' when using the shortcuts for times\\.","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/whenever/cron.rb","lineNumber":80,"sourceCode":"      end\n\n      def parse_symbol\n        shortcut = case @time\n          when *KEYWORDS then \"@#{@time}\" # :reboot => '@reboot'\n          when :year     then Whenever.seconds(1, :year)\n          when :day      then Whenever.seconds(1, :day)\n          when :month    then Whenever.seconds(1, :month)\n          when :week     then Whenever.seconds(1, :week)\n          when :hour     then Whenever.seconds(1, :hour)\n          when :minute   then Whenever.seconds(1, :minute)\n        end\n\n        if shortcut.is_a?(Numeric)\n          @time = shortcut\n          parse_time\n        elsif shortcut\n          if @at.is_a?(Time) || (@at.is_a?(Numeric) && @at > 0)\n            raise ArgumentError, \"You cannot specify an ':at' when using the shortcuts for times.\"\n          else\n            return shortcut\n          end\n        else\n          parse_as_string\n        end\n      end\n\n      def parse_time\n        timing = Array.new(5, '*')\n        case @time\n          when Whenever.seconds(0, :seconds)...Whenever.seconds(1, :minute)\n            raise ArgumentError, \"Time must be in minutes or higher\"\n          when Whenever.seconds(1, :minute)...Whenever.seconds(1, :hour)\n            minute_frequency = @time / 60\n            timing[0] = comma_separated_timing(minute_frequency, 59, @at || 0)\n          when Whenever.seconds(1, :hour)...Whenever.seconds(1, :day)\n            hour_frequency = (@time / 60 / 60).round","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/javan/whenever/blob/756163ed1aa928c8abd629aa2f4904bc5226538c/lib/whenever/cron.rb#L62-L98","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Replace the keyword with an interval: every 1.day, at: '4pm' (or the equivalent symbols :day, :hour, :week, :month, :year).","Drop the :at option and accept the @-shortcut's fixed cron time (e.g. @daily runs at midnight).","Use raw cron syntax for full control: every '0 16 * * *' for 4pm daily.","If generating schedules programmatically, check Whenever::Output::Cron::KEYWORDS before attaching :at."],"exampleFix":"# before\nevery :daily, at: '4:30pm' do\n  rake 'logs:clear'\nend\n\n# after\nevery 1.day, at: '4:30pm' do\n  rake 'logs:clear'\nend","handlingStrategy":"validation","validationCode":"AT_KEYWORDS = %i[reboot yearly annually monthly weekly daily midnight hourly]\nif AT_KEYWORDS.include?(frequency) && options.key?(:at)\n  abort('at: cannot be combined with the ' + frequency.inspect + ' shortcut; use an interval such as 1.day instead')\nend\nevery frequency, options","typeGuard":"def accepts_at?(time)\n  !%i[reboot yearly annually monthly weekly daily midnight hourly].include?(time)\nend","tryCatchPattern":"begin\n  Whenever.cron(file: 'config/schedule.rb')\nrescue ArgumentError => e\n  abort('config/schedule.rb invalid: ' + e.message)\nend","preventionTips":["Reserve @ keyword shortcuts for jobs without a time of day; use interval values (1.day, :hour) whenever :at is needed.","Run a bare `whenever` in CI — it prints the converted schedule without writing the crontab and fails fast on DSL errors.","Keep a unit test that evaluates the schedule file so refactors from 1.day to :daily with a leftover :at break the build."],"tags":["ruby","cron","scheduling","argumenterror","dsl"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"756163ed1aa928c8abd629aa2f4904bc5226538c","analyzedAt":"2026-08-21T18:07:39.974Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}