{"record":{"id":"9d883d7c2c4fa5b9","repo":"puppetlabs/puppet","slug":"repeat-must-be-a-number","errorCode":null,"errorMessage":"Repeat must be a number","messagePattern":"Repeat must be a number","errorType":"validation","errorClass":"Puppet::Error","httpStatus":null,"severity":"error","filePath":"lib/puppet/type/schedule.rb","lineNumber":283,"sourceCode":"\n          # If the number of seconds between the two times is greater\n          # than the unit of time, we match.  We divide the scale\n          # by the repeat, so that we'll repeat that often within\n          # the scale.\n          (now.to_i - previous.to_i) >= (scale / @resource[:repeat])\n        end\n      end\n    end\n\n    newparam(:repeat) do\n      desc \"How often a given resource may be applied in this schedule's `period`.\n        Must be an integer.\"\n\n      defaultto 1\n\n      validate do |value|\n        unless value.is_a?(Integer) or value =~ /^\\d+$/\n          raise Puppet::Error,\n                _(\"Repeat must be a number\")\n        end\n\n        # This implicitly assumes that 'periodmatch' is distance -- that\n        # is, if there's no value, we assume it's a valid value.\n        return unless @resource[:periodmatch]\n\n        if value != 1 and @resource[:periodmatch] != :distance\n          raise Puppet::Error,\n                _(\"Repeat must be 1 unless periodmatch is 'distance', not '%{period}'\") % { period: @resource[:periodmatch] }\n        end\n      end\n\n      munge do |value|\n        value = Integer(value) unless value.is_a?(Integer)\n\n        value\n      end","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/type/schedule.rb#L265-L301","documentation":"The schedule type's `repeat` parameter (applications allowed per period) validates that the value is an Integer or a digit-only string; otherwise Puppet::Error \"Repeat must be a number\" (lib/puppet/type/schedule.rb:283). Note the regex has no minus sign or decimal point: '-1' and '1.5' fail, and a Ruby Float like 2.0 fails both checks too.","triggerScenarios":"`schedule { 'm': period => hourly, repeat => '1.5' }`; `repeat => 'always'`; `repeat => 2.0` (Float literal from YAML); `repeat => -1`.","commonSituations":"YAML-loaded values becoming Floats (2.0 instead of 2); users wanting fractional frequency; passing words from a UI dropdown.","solutions":["Pass a plain integer or digit-only string, e.g. repeat => 2","Fix the data source: cast to Integer in profile code or correct the YAML to an int","For finer granularity, shorten `period` instead of using fractional repeat"],"exampleFix":"# before\nschedule { 'backups':\n  period => hourly,\n  repeat => '1.5',\n}\n\n# after\nschedule { 'backups':\n  period => hourly,\n  repeat => 1,\n}","handlingStrategy":"validation","validationCode":"$repeat = Integer.new($repeat_raw) # fails early with a clear message\nif $repeat < 1 { fail('repeat must be >= 1') }","typeGuard":"def valid_repeat?(v)\n  v.is_a?(Integer) || (v.is_a?(String) && v =~ /\\A\\d+\\z/)\nend","tryCatchPattern":"begin\n  Puppet::Type.type(:schedule).new(name: 'm', period: :hourly, repeat: '1.5')\nrescue Puppet::Error => e\n  raise unless e.message.include?('Repeat must be a number')\n  # Integer()-coerce the value and rebuild\nend","preventionTips":["Force Integer type on repeat inputs in Puppet 4+ signatures","Watch for YAML turning 2 into 2.0 (quote or cast)","Remember repeat interacts with periodmatch (see next error)"],"tags":["puppet","schedule","invalid-value","repeat"],"backgroundTag":"invalid-parameter-value","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}