puppetlabs/puppet · error · ArgumentError
The code loaded from %{source_ref} produced plan with the wr
Error message
The code loaded from %{source_ref} produced plan with the wrong name, expected %{expected}, actual %{actual} What it means
Raised by PuppetPlanInstantiator when the plan file's sole definition is a plan, but its declared name differs from the typed name the loader is binding (derived from the module name plus the file path). A plan named mymod::deploy must live in modules/mymod/plans/deploy.pp; subdirectories add name segments (plans/sub/foo.pp expects mymod::sub::foo).
Source
Thrown at lib/puppet/pops/loader/puppet_plan_instantiator.rb:51
# Only one plan is allowed (and no other definitions)
case definitions.size
when 0
raise ArgumentError, _("The code loaded from %{source_ref} does not define the plan '%{plan_name}' - it is empty.") % { source_ref: source_ref, plan_name: typed_name.name }
when 1
# ok
else
raise ArgumentError, _("The code loaded from %{source_ref} must contain only the plan '%{plan_name}' - it has additional definitions.") % { source_ref: source_ref, plan_name: typed_name.name }
end
the_plan_definition = definitions[0]
unless the_plan_definition.is_a?(Model::PlanDefinition)
raise ArgumentError, _("The code loaded from %{source_ref} does not define the plan '%{plan_name}' - no plan found.") % { source_ref: source_ref, plan_name: typed_name.name }
end
unless the_plan_definition.name == typed_name.name
expected = typed_name.name
actual = the_plan_definition.name
raise ArgumentError, _("The code loaded from %{source_ref} produced plan with the wrong name, expected %{expected}, actual %{actual}") % { source_ref: source_ref, expected: expected, actual: actual }
end
unless result.body == the_plan_definition
raise ArgumentError, _("The code loaded from %{source} contains additional logic - can only contain the plan %{plan_name}") % { source: source_ref, plan_name: typed_name.name }
end
# Adapt the function definition with loader - this is used from logic contained in it body to find the
# loader to use when making calls to the new function API. Such logic have a hard time finding the closure (where
# the loader is known - hence this mechanism
private_loader = loader.private_loader
Adapters::LoaderAdapter.adapt(the_plan_definition).loader_name = private_loader.loader_name
# Cannot bind loaded functions to global scope, that must be done without binding that scope as
# loaders survive a compilation.
closure_scope = nil
created = create_function_class(the_plan_definition)
# create the function instance - it needs closure (scope), and loader (i.e. where it should start searching for things
# when calling functions etc.View on GitHub (pinned to e227c27540)
Solutions
- Make the plan statement name exactly match the module::path-derived name
- Rename the file to match the plan name if the plan name is the desired one
- Check subdirectory mapping: plans/sub/foo.pp must declare mymod::sub::foo
Example fix
# before - modules/mymod/plans/deploy.pp
plan mymod::deploy_prod($n) { run_command('uptime', $n) }
# after
plan mymod::deploy($n) { run_command('uptime', $n) } Defensive patterns
Strategy: validation
Validate before calling
expected = "#{module_name}::#{File.basename(path, '.pp')}"
ok = defs[0].is_a?(Puppet::Pops::Model::PlanDefinition) && defs[0].name == expected
raise ArgumentError, "plan name #{defs[0].name} != #{expected}" unless ok Try / catch
begin
loader.load_typed(typed_name)
rescue ArgumentError => e
raise unless e.message.include?('wrong name')
warn "plan/file name mismatch: #{e.message}"
end Prevention
- Derive the plan statement name from the file path when creating plans
- Rename file and plan statement together in one change
- Include subdirectory segments in the plan namespace (plans/sub/x.pp is mod::sub::x)
When it happens
Trigger: `the_plan_definition.name != typed_name.name`: e.g. plans/deploy.pp contains `plan mymod::deploy_prod(...)` while the loader resolves typed name mymod::deploy from the path.
Common situations: Renaming a plan file but not the plan statement (or vice versa); copy-pasting a plan and editing only one of the two names; adding/removing subdirectory segments without updating the plan's namespace.
Related errors
- The code loaded from %{source_ref} does not define the plan
- The code loaded from %{source_ref} must contain only the pla
- The code loaded from %{source_ref} does not define the plan
- The code loaded from %{source} contains additional logic - c
- The code loaded from %{source_ref} produced resource type wi
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/6ff2072dedcefe6d.
Report an issue: GitHub.