{"record":{"id":"d06346af7021226a","repo":"puppetlabs/puppet","slug":"invalid-hour-n","errorCode":null,"errorMessage":"Invalid hour '%{n}'","messagePattern":"Invalid hour '%(.+?)'","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/type/schedule.rb","lineNumber":131,"sourceCode":"\n        values.each { |value|\n          range = []\n          # Split each range value into a hour, minute, second triad\n          value.split(/\\s*-\\s*/).each { |val|\n            # Add the values as an array.\n            range << val.split(\":\").collect(&:to_i)\n          }\n\n          self.fail _(\"Invalid range %{value}\") % { value: value } if range.length != 2\n\n          # Fill out 0s for unspecified minutes and seconds\n          range.each do |time_array|\n            (3 - time_array.length).times { |_| time_array << 0 }\n          end\n\n          # Make sure the hours are valid\n          [range[0][0], range[1][0]].each do |n|\n            raise ArgumentError, _(\"Invalid hour '%{n}'\") % { n: n } if n < 0 or n > 23\n          end\n\n          [range[0][1], range[1][1]].each do |n|\n            raise ArgumentError, _(\"Invalid minute '%{n}'\") % { n: n } if n and (n < 0 or n > 59)\n          end\n          ret << range\n        }\n\n        # Now our array of arrays\n        ret\n      end\n\n      def weekday_match?(day)\n        if @resource[:weekday]\n          @resource[:weekday].has_key?(day)\n        else\n          true\n        end","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/type/schedule.rb#L113-L149","documentation":"The schedule type's `range` parameter parses 'HH:MM-HH:MM[:SS]' strings; each endpoint is split on ':' and cast with to_i, minutes/seconds default to 0. Each endpoint's hour must be within 0–23 or ArgumentError \"Invalid hour\" is raised (lib/puppet/type/schedule.rb:131). Note 24 is invalid — the day wraps to 0.","triggerScenarios":"`schedule { 'm': range => '25:00-27:00' }`; `range => '20:00-24:00'` (24 out of range — write 23:59:59 or cross midnight with two ranges); computed hours from templates that overflow past 23.","commonSituations":"Assuming 24:00 means end-of-day; copy-pasting 12-hour times without converting; maintenance-window templates computing `start + duration` that produce 24+.","solutions":["Use hours 0–23 only; express end-of-day as 23:59:59","For windows crossing midnight, use two ranges (e.g. '20:00-23:59:59' and '0:00-2:00') since Puppet treats ranges as within a single day","Fix template arithmetic that computes hour 24"],"exampleFix":"# before\nschedule { 'maintenance':\n  range => '20:00-24:00',\n}\n\n# after\nschedule { 'maintenance':\n  range => '20:00-23:59:59',\n}","handlingStrategy":"validation","validationCode":"[$start_hour, $end_hour].all |Integer $h| { $h >= 0 and $h <= 23 } or\nfail('schedule range hours must be 0-23')","typeGuard":"def valid_hours?(start_h, end_h)\n  [start_h, end_h].all? { |h| h.is_a?(Integer) && h.between?(0, 23) }\nend","tryCatchPattern":"begin\n  Puppet::Type.type(:schedule).new(name: 'm', range: '25:00-27:00')\nrescue ArgumentError => e\n  raise unless e.message.include?(\"Invalid hour\")\n  # clamp/fix hours to 0-23 and rebuild\nend","preventionTips":["Remember hours are 24-hour 0–23, no 24:00 endpoint","Compute ranges in profile code and assert bounds before declaring","Prefer explicit minute granularity (23:59) over 24:00"],"tags":["puppet","schedule","time-range","validation"],"backgroundTag":"invalid-time-range","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}