puppetlabs/puppet · error · ArgumentError

A block must be given to 'in_environment'

Error message

A block must be given to 'in_environment'

What it means

Puppet::Pal.in_environment requires a block for the same reason as the other PAL entry points: the environment context (resolved from env_dir or envpath) is established only for the block's duration. Missing block raises ArgumentError.

Source

Thrown at lib/puppet/pal/pal_impl.rb:295

  def self.in_environment(env_name,
                          modulepath: nil,
                          pre_modulepath: [],
                          post_modulepath: [],
                          settings_hash: {},
                          env_dir:       nil,
                          envpath:       nil,
                          facts:         nil,
                          variables:     {},
                          &block)
    # TRANSLATORS terms in the assertions below are names of terms in code
    assert_non_empty_string(env_name, 'env_name')
    assert_optionally_empty_array(modulepath, 'modulepath', true)
    assert_optionally_empty_array(pre_modulepath, 'pre_modulepath', false)
    assert_optionally_empty_array(post_modulepath, 'post_modulepath', false)
    assert_mutually_exclusive(env_dir, envpath, 'env_dir', 'envpath')

    unless block_given?
      raise ArgumentError, _("A block must be given to 'in_environment'") # TRANSLATORS 'in_environment' is a name, do not translate
    end

    if env_dir
      unless Puppet::FileSystem.exist?(env_dir)
        raise ArgumentError, _("The environment directory '%{env_dir}' does not exist") % { env_dir: env_dir }
      end

      # a nil modulepath for env_dir means it should use its ./modules directory
      mid_modulepath = modulepath.nil? ? [Puppet::FileSystem.expand_path(File.join(env_dir, 'modules'))] : modulepath

      env = Puppet::Node::Environment.create(env_name, pre_modulepath + mid_modulepath + post_modulepath)
      environments = Puppet::Environments::StaticDirectory.new(env_name, env_dir, env) # The env being used is the only one...
    else
      assert_non_empty_string(envpath, 'envpath')

      # The environment is resolved against the envpath. This is setup without a basemodulepath
      # The modulepath defaults to the 'modulepath' in the found env when "Directories" is used
      #

View on GitHub (pinned to e227c27540)

Solutions

  1. Supply the block that receives the pal compiler context
  2. Forward &block through every wrapper layer
  3. Fail fast in your wrapper with a clearer message using block_given?

Example fix

# before
Puppet::Pal.in_environment('prod', env_dir: dir)

# after
Puppet::Pal.in_environment('prod', env_dir: dir) do |pal|
  # compile / evaluate
end
Defensive patterns

Strategy: validation

Validate before calling

raise ArgumentError, 'block required' unless block_given?
Puppet::Pal.in_environment(name, env_dir: dir, &block)

Prevention

When it happens

Trigger: Puppet::Pal.in_environment('production', envpath: path) without a block; delegating wrappers that lose the block.

Common situations: Refactoring PAL calls into helper methods and dropping the &block parameter; scripting examples run partially.

Related errors


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