puppetlabs/puppet · error · ArgumentError

Cannot use empty string as a class name

Error message

Cannot use empty string as a class name

What it means

Raised by Scope#transform_and_assert_classnames in the String branch when the class name argument is '' (empty). An empty string usually means a variable interpolation or lookup produced nothing textual, e.g. building a class name dynamically and one fragment was empty. Like the undef case it is an ArgumentError from class-name normalization.

Source

Thrown at lib/puppet/parser/scope.rb:1086

  # lookup in the compiler.
  #
  # Makes names passed in the names array absolute if they are relative.
  #
  # Transforms Class[] and Resource[] type references to class name
  # or raises an error if a Class[] is unspecific, if a Resource is not
  # a 'class' resource, or if unspecific (no title).
  #
  #
  # @param names [Array<String>] names to (optionally) make absolute
  # @return [Array<String>] names after transformation
  #
  def transform_and_assert_classnames(names)
    names.map do |name|
      case name
      when NilClass
        raise ArgumentError, _("Cannot use undef as a class name")
      when String
        raise ArgumentError, _("Cannot use empty string as a class name") if name.empty?

        name.sub(/^([^:]{1,2})/, '::\1')

      when Puppet::Resource
        assert_class_and_title(name.type, name.title)
        name.title.sub(/^([^:]{1,2})/, '::\1')

      when Puppet::Pops::Types::PClassType
        # TRANSLATORS "Class" and "Type" are Puppet keywords and should not be translated
        raise ArgumentError, _("Cannot use an unspecific Class[] Type") unless name.class_name

        name.class_name.sub(/^([^:]{1,2})/, '::\1')

      when Puppet::Pops::Types::PResourceType
        assert_class_and_title(name.type_name, name.title)
        name.title.sub(/^([^:]{1,2})/, '::\1')
      end.downcase
    end

View on GitHub (pinned to e227c27540)

Solutions

  1. Guard the composed name: `if $role != '' and $role != undef { include "profile::${role}" }`.
  2. Fail fast with a clearer error at the source: `assert_type(NonEmptyString, $role)` before composing the name.
  3. Fix the upstream data so the interpolated fragment is always populated (Hiera key, fact).

Example fix

# before
include "profile::${server_role}"   # $server_role == '' -> Cannot use empty string as a class name

# after
if $server_role =~ NonEmptyString {
  include "profile::${server_role}"
} else {
  fail("server_role must be set, got '${server_role}'")
}
Defensive patterns

Strategy: type-guard

Validate before calling

$name = "profile::${role}"
fail("empty role") unless $name =~ NonEmptyString

Type guard

if "profile::${role}" =~ NonEmptyString {
  include "profile::${role}"
}

Prevention

When it happens

Trigger: `include "${prefix}"` with $prefix unset-but-not-strict (interpolates to ''); `include "profile::${role}"` when $role is '' from Hiera; API calls passing '' to include/contain or transform_and_assert_classnames.

Common situations: Role/profile patterns composing class names from node data where a role fact is empty on some nodes; migrations where a variable was renamed and interpolations silently yield empty strings; hiera lookups defaulting to ''.

Related errors


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