{"record":{"id":"58cb05164db503e2","repo":"puppetlabs/puppet","slug":"repeat-must-be-1-unless-periodmatch-is-distance","errorCode":null,"errorMessage":"Repeat must be 1 unless periodmatch is 'distance', not '%{period}'","messagePattern":"Repeat must be 1 unless periodmatch is 'distance', not '%(.+?)'","errorType":"validation","errorClass":"Puppet::Error","httpStatus":null,"severity":"error","filePath":"lib/puppet/type/schedule.rb","lineNumber":292,"sourceCode":"\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\n\n      def match?(previous, now)\n        true\n      end\n    end\n\n    newparam(:weekday) do\n      desc <<-EOT\n        The days of the week in which the schedule should be valid.","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/type/schedule.rb#L274-L310","documentation":"A schedule's `repeat` > 1 is only meaningful when `periodmatch` is 'distance' (periods measured as distance since epoch). The validate raises Puppet::Error \"Repeat must be 1 unless periodmatch is 'distance'\" (lib/puppet/type/schedule.rb:292) when repeat != 1 and periodmatch is set to something else — in practice 'number' (calendar-matched periods).","triggerScenarios":"`schedule { 'x': period => daily, periodmatch => number, repeat => 3 }`; setting periodmatch => number in a shared schedule define while another layer sets repeat.","commonSituations":"Users switching periodmatch to 'number' for calendar semantics while keeping a repeat count; module upgrades that exposed both knobs.","solutions":["Set `periodmatch => distance` (the default) when using repeat > 1","Or keep `repeat => 1` and change `period` granularity instead","Remove the explicit periodmatch if you actually want distance semantics"],"exampleFix":"# before\nschedule { 'backups':\n  period      => daily,\n  periodmatch => number,\n  repeat      => 3,\n}\n\n# after\nschedule { 'backups':\n  period      => daily,\n  periodmatch => distance,\n  repeat      => 3,\n}","handlingStrategy":"validation","validationCode":"if $repeat != 1 and $periodmatch != undef and $periodmatch != 'distance' {\n  fail(\"repeat > 1 requires periodmatch => distance, got '${periodmatch}'\")\n}","typeGuard":"def repeat_periodmatch_ok?(repeat, periodmatch)\n  repeat == 1 || periodmatch.to_s == 'distance'\nend","tryCatchPattern":"begin\n  Puppet::Type.type(:schedule).new(\n    name: 'x', period: :daily, periodmatch: :number, repeat: 3\n  )\nrescue Puppet::Error => e\n  raise unless e.message.include?('periodmatch')\n  # switch periodmatch to :distance or set repeat to 1\nend","preventionTips":["Read the schedule docs: repeat counts per distance-period bucket only","Single-source schedule definitions instead of composing periodmatch and repeat from different layers","rspec-puppet compile tests for schedule profiles"],"tags":["puppet","schedule","parameter-conflict","repeat"],"backgroundTag":"mutually-exclusive-parameters","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}