puppetlabs/puppet · error · InvalidName
Task names must start with a lowercase letter and be compose
Error message
Task names must start with a lowercase letter and be composed of only lowercase letters, numbers, and underscores
What it means
Raised by Puppet::Module::Task#initialize when a task name fails Puppet::Module::Task.is_task_name?. Task names become the middle segment of the fully-qualified task name (module::taskname) and must start with a lowercase letter and contain only lowercase letters, digits, and underscores. Names are derived from filenames in the module's tasks/ directory, so an invalid filename makes every task in that module unlistable.
Source
Thrown at lib/puppet/module/task.rb:230
def self.tasks_in_module(pup_module)
task_files = Dir.glob(File.join(pup_module.tasks_directory, '*'))
.keep_if { |f| is_tasks_file?(f) }
module_executables = task_files.reject(&method(:is_tasks_metadata_filename?)).map.to_a
tasks = task_files.group_by { |f| task_name_from_path(f) }
tasks.map do |task, executables|
new_with_files(pup_module, task, executables, module_executables)
end
end
attr_reader :name, :module, :metadata_file
# file paths must be relative to the modules task directory
def initialize(pup_module, task_name, module_executables, metadata_file = nil)
unless Puppet::Module::Task.is_task_name?(task_name)
raise InvalidName, _("Task names must start with a lowercase letter and be composed of only lowercase letters, numbers, and underscores")
end
name = task_name == "init" ? pup_module.name : "#{pup_module.name}::#{task_name}"
@module = pup_module
@name = name
@metadata_file = metadata_file
@module_executables = module_executables || []
end
def self.read_metadata(file)
if file
content = Puppet::FileSystem.read(file, :encoding => 'utf-8')
content.empty? ? {} : Puppet::Util::Json.load(content)
end
rescue SystemCallError, IOError => err
msg = _("Error reading metadata: %{message}" % { message: err.message })
raise InvalidMetadata.new(msg, 'puppet.tasks/unreadable-metadata')View on GitHub (pinned to e227c27540)
Solutions
- Rename the offending file(s) in the module's tasks/ directory to /^[a-z][a-z0-9_]*$/ (e.g. 'restart_service.sh' -> 'restart_service.sh' kept, 'Restart-Service.sh' -> 'restart_service.sh').
- Delete stray non-task files (backups, swap files, .DS_Store) from tasks/.
- If you need word separation, use underscores, never dashes.
- Verify with `puppet module tasks list <module>` or `bolt task show`.
Example fix
# before: modules/mymodule/tasks/Restart-Service.py # after: modules/mymodule/tasks/restart_service.py
Defensive patterns
Strategy: validation
Validate before calling
task_name = File.basename(file, File.extname(file))
unless task_name.match?(\A[a-z][a-z0-9_]*\z)
warn "skipping invalid task file #{file}"; next
end Type guard
def task_name?(str) str.is_a?(String) && str.match?(\A[a-z][a-z0-9_]*\z) end
Try / catch
begin
Puppet::Module::Task.new_with_files(mod, name, executables)
rescue Puppet::Module::Task::InvalidName => e
warn "invalid task name #{name}: #{e.message}"
end Prevention
- Generate tasks with `bolt task new <module> <task>` so naming conventions are followed.
- Keep task filenames lowercase snake_case; reject dashes/uppercase in code review.
- Exclude editor backup files (#{...}#, *.swp, .DS_Store) from tasks/ via clean checkouts.
When it happens
Trigger: A file in tasks/ such as 'MyTask.sh', '2restart.rb', 'my-task.py', or 'task.name' — the basename before the first extension is passed to is_task_name? when Task.instances or Task.new is constructed; the first bad file raises Puppet::Module::Task::InvalidName and aborts task discovery for the run.
Common situations: Copying a bolt plan/script with dashes into tasks/; Windows-origin files with uppercase names; test fixtures or editor swap files (e.g. '#task.rb#') left in tasks/; subdirectories with unsupported names.
Related errors
- Invalid mount name format '%{name}'
- Module %{module_name} not found in environment %{environment
- Invalid module name '%{name}'; module names must match eithe
- Could not find %{path} on disk
- PathPatterns cannot be created with a zero byte.
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/e5d6466c3f58fe78.
Report an issue: GitHub.