puppetlabs/puppet · error · ArgumentError
The code loaded from %{source_ref} does not seem to be a Pup
Error message
The code loaded from %{source_ref} does not seem to be a Puppet 4x API function - no create_function call. What it means
Raised by RubyFunctionInstantiator when Ruby source loaded as a 4x API function does not contain a Puppet::Functions.create_function call (regex gate before eval). Modern Ruby functions live in lib/puppet/functions/ (namespaced) and must be defined via create_function; anything else fails fast.
Source
Thrown at lib/puppet/pops/loader/ruby_function_instantiator.rb:19
# frozen_string_literal: true
# The RubyFunctionInstantiator instantiates a Puppet::Functions::Function given the ruby source
# that calls Puppet::Functions.create_function.
#
class Puppet::Pops::Loader::RubyFunctionInstantiator
# Produces an instance of the Function class with the given typed_name, or fails with an error if the
# given ruby source does not produce this instance when evaluated.
#
# @param loader [Puppet::Pops::Loader::Loader] The loader the function is associated with
# @param typed_name [Puppet::Pops::Loader::TypedName] the type / name of the function to load
# @param source_ref [URI, String] a reference to the source / origin of the ruby code to evaluate
# @param ruby_code_string [String] ruby code in a string
#
# @return [Puppet::Pops::Functions.Function] - an instantiated function with global scope closure associated with the given loader
#
def self.create(loader, typed_name, source_ref, ruby_code_string)
unless ruby_code_string.is_a?(String) && ruby_code_string =~ /Puppet::Functions\.create_function/
raise ArgumentError, _("The code loaded from %{source_ref} does not seem to be a Puppet 4x API function - no create_function call.") % { source_ref: source_ref }
end
# make the private loader available in a binding to allow it to be passed on
loader_for_function = loader.private_loader
here = get_binding(loader_for_function)
created = eval(ruby_code_string, here, source_ref, 1) # rubocop:disable Security/Eval
unless created.is_a?(Class)
raise ArgumentError, _("The code loaded from %{source_ref} did not produce a Function class when evaluated. Got '%{klass}'") % { source_ref: source_ref, klass: created.class }
end
unless created.name.to_s == typed_name.name()
raise ArgumentError, _("The code loaded from %{source_ref} produced mis-matched name, expected '%{type_name}', got %{created_name}") % { source_ref: source_ref, type_name: typed_name.name, created_name: created.name }
end
# create the function instance - it needs closure (scope), and loader (i.e. where it should start searching for things
# when calling functions etc.
# It should be bound to global scope
# Sets closure scope to nil, to let it be picked up at runtime from Puppet.lookup(:global_scope)View on GitHub (pinned to e227c27540)
Solutions
- Rewrite the function using Puppet::Functions.create_function(:'mod::name') do ... end
- Keep legacy 3x functions under lib/puppet/parser/functions/<name>.rb so the legacy instantiator handles them
- Verify the source_ref to confirm which file the 4x loader is opening
Example fix
# before - lib/puppet/functions/mymod/double.rb
module Puppet::Parser::Functions
newfunction(:double, :type => :rvalue) { |args| args[0] * 2 }
end
# after
Puppet::Functions.create_function(:'mymod::double') do
dispatch :double do
param 'Integer', :x
end
def double(x); x * 2; end
end Defensive patterns
Strategy: validation
Validate before calling
raise ArgumentError, "#{path} is not a Puppet 4x function" unless ruby_source.is_a?(String) && ruby_source =~ /Puppet::Functions\.create_function/ Try / catch
begin
fn = loader.load_typed(typed_name)
rescue ArgumentError => e
raise unless e.message.include?('no create_function call')
warn "not a 4x Ruby function: #{e.message}"
end Prevention
- Put 4x functions only in lib/puppet/functions/ with module namespacing
- Put 3x functions only in lib/puppet/parser/functions/
- Automate 3x-to-4x migration with a conversion tool, then grep directories for the wrong API
When it happens
Trigger: `ruby_code_string !~ /Puppet::Functions\.create_function/`: a .rb file resolved as a 4x function lacks the call -- e.g. legacy 3x `newfunction` code left where the 4x loader finds it, or plain Ruby helpers in the functions path.
Common situations: Migrating 3x functions while files remain in or resolve through 4x paths; writing plain Ruby utility classes in lib/puppet/functions/; broken packaging that ships the wrong file under the function name.
Related errors
- The code loaded from %{source_ref} did not produce a Functio
- The code loaded from %{source_ref} does not seem to be a Pup
- The code loaded from %{source_ref} did not produce a data ty
- The code loaded from %{source_ref} produced mis-matched name
- The code loaded from %{source_ref} does not seem to be a Pup
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/7584c3d91943d340.
Report an issue: GitHub.