puppetlabs/puppet · error · ArgumentError

Cannot transform a number to a tag

Error message

Cannot transform a number to a tag

What it means

Raised inside Puppet::Pops::Evaluator::CollectorTransformer while translating a collection search expression whose operator is '==' with left side 'tag'. Tag comparisons are compiled into a static tag list used by resource.raw_tagged?; a Numeric literal on the right cannot be a tag (tags are strings), so transformation aborts with ArgumentError before any resource is collected.

Source

Thrown at lib/puppet/pops/evaluator/collector_transformer.rb:107

    end
  end

  def query_ComparisonExpression(o, scope)
    left_code = query(o.left_expr, scope)
    right_code = query(o.right_expr, scope)

    case o.operator
    when '=='
      if left_code == "tag"
        # Ensure that to_s and downcase is done once, i.e. outside the proc block and
        # then use raw_tagged? instead of tagged?
        if right_code.is_a?(Array)
          tags = right_code
        else
          tags = [right_code]
        end
        tags = tags.collect do |t|
          raise ArgumentError, _('Cannot transform a number to a tag') if t.is_a?(Numeric)

          t.to_s.downcase
        end
        proc do |resource|
          resource.raw_tagged?(tags)
        end
      else
        proc do |resource|
          if (tmp = resource[left_code]).is_a?(Array)
            @@compare_operator.include?(tmp, right_code, scope)
          else
            @@compare_operator.equals(tmp, right_code)
          end
        end
      end
    when '!='
      proc do |resource|
        !@@compare_operator.equals(resource[left_code], right_code)

View on GitHub (pinned to e227c27540)

Solutions

  1. Quote the tag: `<| tag == '5' |>` — tags are always compared as strings.
  2. When building the right side dynamically, coerce first: `"${number}"` or `.to_s`.
  3. If the intent was a numeric attribute comparison, use the attribute name instead of `tag`.

Example fix

# before
File<| tag == 42 |>   # Cannot transform a number to a tag

# after
File<| tag == '42' |>
Defensive patterns

Strategy: type-guard

Validate before calling

# Coerce dynamic operands to strings before building collectors:
$tag_val = "${port}"    # not the Integer

Type guard

# Conceptually what the transformer requires:
# right operand of `tag ==` must be String or Array<String>
tags.all? { |t| t.is_a?(String) }

Prevention

When it happens

Trigger: `<| tag == 5 |>`, `User<| tag == 42 |>`, or `Tag<| tag == 1 |>`-style collector statements with a bare numeric literal. Also generated collectors where the right operand is an Integer value rather than a String/Array.

Common situations: Copy-paste from docs where tags were quoted; dynamically built search expressions interpolating numbers without quoting; refactoring resource collections during module upgrades.

Related errors


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