puppetlabs/puppet · error · ArgumentError

Invalid hold value %{value}. %{doc}

Error message

Invalid hold value %{value}. %{doc}

What it means

The package type's `mark` property manages hold/pin state and only accepts the values `hold` or `none` (newvalues + munge in lib/puppet/type/package.rb:684). Any other value — 'held', true, 'unhold', symbols, hashes — falls into the munge's else branch and raises ArgumentError with the value inspected plus the mark documentation text.

Source

Thrown at lib/puppet/type/package.rb:684

      desc <<-EOT
        Set to hold to tell Debian apt/Solaris pkg to hold the package version

        #{mark_doc}
        Default is "none". Mark can be specified with or without `ensure`,
        if `ensure` is missing will default to "present".

        Mark cannot be specified together with "purged", or "absent"
        values for `ensure`.
      EOT
      newvalues(:hold, :none)
      munge do |value|
        case value
        when "hold", :hold
          :hold
        when "none", :none
          :none
        else
          raise ArgumentError, _('Invalid hold value %{value}. %{doc}') % { value: value.inspect, doc: mark_doc }
        end
      end

      def insync?(is)
        @should[0] == is
      end

      def should
        @should[0] if @should && @should.is_a?(Array) && @should.size == 1
      end

      def retrieve
        provider.properties[:mark]
      end

      def sync
        if @should[0] == :hold
          provider.hold

View on GitHub (pinned to e227c27540)

Solutions

  1. Use exactly `mark => hold` or `mark => none`
  2. If you were migrating old `ensure => held` syntax, replace it with `mark => hold` (held is no longer an ensure value)
  3. Type the variable in your module data as Enum['hold', 'none'] so invalid data fails earlier with a clearer message

Example fix

# before
package { 'nginx':
  ensure => installed,
  mark   => 'held',
}

# after
package { 'nginx':
  ensure => installed,
  mark   => hold,
}
Defensive patterns

Strategy: validation

Validate before calling

if $mark != undef and $mark !~ /^(hold|none)$/ {
  fail("package mark must be 'hold' or 'none', got '${mark}'")
}

Type guard

def valid_mark?(value)
  %w[hold none].include?(value.to_s)
end

Try / catch

begin
  Puppet::Type.type(:package).new(name: 'nginx', ensure: :installed, mark: 'held')
rescue ArgumentError => e
  raise unless e.message.include?('Invalid hold value')
  # normalize to :hold/:none and retry construction once
end

Prevention

When it happens

Trigger: Writing `package { 'nginx': mark => 'held' }`, `mark => true`, `mark => 'hold '` (trailing space), or programmatically `Puppet::Type.type(:package).new(name: 'x', mark: 'frozen')`.

Common situations: Users arriving from `apt-mark hold` writing 'held'; users confusing provider-specific words ('frozen', 'pinned', 'locked'); manifests migrated from ancient `ensure => held` syntax that must become `mark => hold` after upgrades.

Related errors


AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21). Data as JSON: /api/errors/ec3cb39256b95ff8. Report an issue: GitHub.