puppetlabs/puppet · error · Puppet::Error

manifest of environment '#{@environment.name}' appoints dire

Error message

manifest of environment '#{@environment.name}' appoints directory '#{file}'. It must be a file

What it means

When Puppet::Pops::Loaders loads an environment (no Puppet[:code] set), it reads @environment.manifest — the `manifest` setting from environment.conf (or its default). After the NO_MANIFEST escape, it explicitly requires a regular file: File.directory?(file) raises Puppet::Error. Despite the adjacent comment about combining .pp files, this code path (preloading environment definitions into the loaders) only accepts a single manifest file.

Source

Thrown at lib/puppet/pops/loaders.rb:298

  #     environment as a side effect. This is attempted first.
  #   2. The contents of the environment's +manifest+ attribute: Puppet will
  #     try to load the environment manifest. The manifest must be a file.
  #
  # @return [Model::Program] The manifest parsed into a model object
  def load_main_manifest
    parser = Parser::EvaluatingParser.singleton
    parsed_code = Puppet[:code]
    program = if parsed_code != ""
                parser.parse_string(parsed_code, 'unknown-source-location')
              else
                file = @environment.manifest

                # if the manifest file is a reference to a directory, parse and
                # combine all .pp files in that directory
                if file == Puppet::Node::Environment::NO_MANIFEST
                  nil
                elsif File.directory?(file)
                  raise Puppet::Error, "manifest of environment '#{@environment.name}' appoints directory '#{file}'. It must be a file"
                elsif File.exist?(file)
                  parser.parse_file(file)
                else
                  raise Puppet::Error, "manifest of environment '#{@environment.name}' appoints '#{file}'. It does not exist"
                end
              end
    instantiate_definitions(program, public_environment_loader) unless program.nil?
    program
  rescue Puppet::ParseErrorWithIssue => detail
    detail.environment = @environment.name
    raise
  rescue => detail
    msg = _('Could not parse for environment %{env}: %{detail}') % { env: @environment, detail: detail }
    error = Puppet::Error.new(msg)
    error.set_backtrace(detail.backtrace)
    raise error
  end

View on GitHub (pinned to e227c27540)

Solutions

  1. Point the manifest setting at one concrete file, e.g. `manifest = manifests/site.pp`.
  2. If you rely on directory manifests for catalog compilation, keep that in the layer that supports it and give the environment a single entry file for this path.
  3. Set `manifest = ` to the no-manifest sentinel behavior only if you truly have no environment manifest (Puppet::Node::Environment::NO_MANIFEST, i.e. the string 'no_manifest').

Example fix

# before: environments/production/environment.conf
manifest = manifests

# after
manifest = manifests/site.pp
Defensive patterns

Strategy: validation

Validate before calling

# Validate environment.conf manifest before deploy
env_root = 'environments/production'
manifest = nil
File.foreach(File.join(env_root, 'environment.conf')) do |line|
  m = line.match(/^\s*manifest\s*=\s*(\S+)/) and manifest = m[1]
end
if manifest && manifest != 'no_manifest'
  path = File.expand_path(manifest, env_root)
  raise "manifest '#{path}' must be an existing file, not a directory" unless File.file?(path)
end

Prevention

When it happens

Trigger: environment.conf contains `manifest = manifests` or any path that resolves to a directory, and compilation/lookup triggers Loaders#load_environment; Puppet[:code] is empty so the manifest branch runs.

Common situations: Teams setting `manifest` to their manifests/ directory expecting directory-manifest behavior in every code path; site.pp split across files; migrating an environment to environment.conf manifest settings for the first time.

Related errors


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