puppetlabs/puppet · error · ArgumentError

%{name} can't be optional and have a default value

Error message

%{name} can't be optional and have a default value

What it means

Raised by Puppet::Interface::Option#default= (lib/puppet/interface/option.rb:128) when a default-value proc is assigned to an option that is already marked required. An option cannot be both required (caller must pass it) and defaulted (face fills it in when absent), so Puppet rejects the combination at face-definition time. Despite the wording, the guard fires when `required` is truthy: required and default_to are mutually exclusive, whichever is set second loses.

Source

Thrown at lib/puppet/interface/option.rb:128

  def takes_argument?
    !!@argument
  end

  def optional_argument?
    !!@optional_argument
  end

  def required?
    !!@required
  end

  def has_default?
    !!@default
  end

  def default=(proc)
    if required
      raise ArgumentError, _("%{name} can't be optional and have a default value") % { name: self }
    end

    unless proc.is_a? Proc
      # TRANSLATORS 'proc' is a Ruby block of code
      raise ArgumentError, _("default value for %{name} is a %{class_name}, not a proc") %
                           { name: self, class_name: proc.class.name.inspect }
    end
    @default = proc
  end

  def default
    @default and @default.call
  end

  attr_reader :parent, :name, :aliases, :optparse, :required

  def required=(value)
    if has_default?

View on GitHub (pinned to e227c27540)

Solutions

  1. Remove either `required` or `default_to` from the option block — usually drop `required`, since a default already covers the unset case
  2. If the option truly must be supplied, keep `required` and delete `default_to`, letting the face fail when the flag is missing
  3. When driving Option objects directly, only call `default=` when `required?` is false

Example fix

# before
option "--environment" do
  required
  default_to { "production" }
end

# after
option "--environment" do
  default_to { "production" }
end
Defensive patterns

Strategy: validation

Validate before calling

# before assigning a default to an Option object
raise ArgumentError, "#{opt} is required; a default is not allowed" if opt.required?
opt.default = -> { 'production' }

Prevention

When it happens

Trigger: Inside a Faces option block: `option '--environment' do required; default_to { 'production' } end` (required is set first, then default_to assigns via default=). Or calling `opt.default = proc` directly on a Puppet::Interface::Option whose `required?` returns true.

Common situations: Editing a Face where an option changed from required to optional and the old `required` line was left behind; copy-pasting an option block that already contained `required`; programmatically building Options from a config hash that sets required before default.

Related errors


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