puppetlabs/puppet · error · ArgumentError

The given string in encoding '%{enc}' is invalid. Cannot cre

Error message

The given string in encoding '%{enc}' is invalid. Cannot create a Binary UTF-8 representation

What it means

PBinaryType::Binary.from_string builds a Binary by validating the input string in its declared encoding, transcoding to UTF-8, then forcing ASCII-8BIT. If the string contains byte sequences that are invalid in its own encoding, the validity assertion fails with this ArgumentError because no lossless conversion exists.

Source

Thrown at lib/puppet/pops/types/p_binary_type.rb:77

    end

    # Creates a new Binary from a String containing text/binary in its given encoding. If the string's encoding
    # is not already UTF-8, the string is first transcoded to UTF-8.
    # This means that this binary will have the UTF-8 byte representation of the original string.
    # For this to be valid, the encoding used in the given string must be valid.
    # The validity of the given string is therefore asserted.
    #
    # The given string will be frozen as a side effect if it is in ASCII-8BIT encoding. If this is not
    # wanted, a copy should be given to this method.
    #
    # @param [String] A string with valid content in its given encoding
    # @return [Puppet::Pops::Types::PBinaryType::Binary] with the UTF-8 representation of the UTF-8 transcoded string
    # @api public
    #
    def self.from_string(encoded_string)
      enc = encoded_string.encoding.name
      unless encoded_string.valid_encoding?
        raise ArgumentError, _("The given string in encoding '%{enc}' is invalid. Cannot create a Binary UTF-8 representation") % { enc: enc }
      end

      # Convert to UTF-8 (if not already UTF-8), and then to binary
      encoded_string = (enc == "UTF-8") ? encoded_string.dup : encoded_string.encode('UTF-8')
      encoded_string.force_encoding("ASCII-8BIT")
      new(encoded_string)
    end

    # Creates a new Binary from a String containing raw binary data of unknown encoding. If the string's encoding
    # is not already ASCII-8BIT, a copy of the string is forced to ASCII-8BIT (that is Ruby's "binary" format).
    # This means that this binary will have the exact same content, but the string will considered
    # to hold a sequence of bytes in the range 0 to 255.
    #
    # @param [String] A string with binary data
    # @api private
    #
    def initialize(bin)
      @binary_buffer = (bin.encoding.name == "ASCII-8BIT" ? bin : bin.b).freeze

View on GitHub (pinned to e227c27540)

Solutions

  1. If the data is raw bytes of unknown/untrusted encoding, use Binary.from_binary_string(raw.dup) instead — it performs no transcoding.
  2. Fix the upstream read: open files/sockets with 'rb' / set binmode so bytes keep ASCII-8BIT encoding from the start.
  3. Only if losing bad bytes is acceptable, clean the string first: str.scrub!("?") or re-encode from the true source encoding.

Example fix

# before
bin = Puppet::Pops::Types::PBinaryType::Binary.from_string(raw_bytes)

# after
bin = Puppet::Pops::Types::PBinaryType::Binary.from_binary_string(raw_bytes.dup)
Defensive patterns

Strategy: validation

Validate before calling

# Ruby — choose the right constructor up front
if raw.encoding == Encoding::ASCII_8BIT || !raw.valid_encoding?
  bin = Puppet::Pops::Types::PBinaryType::Binary.from_binary_string(raw.dup)
else
  bin = Puppet::Pops::Types::PBinaryType::Binary.from_string(raw)
end

Type guard

def transcodable_string?(s)
  s.is_a?(String) && s.valid_encoding?
end

Try / catch

begin
  Puppet::Pops::Types::PBinaryType::Binary.from_string(s)
rescue ArgumentError
  Puppet::Pops::Types::PBinaryType::Binary.from_binary_string(s.dup) # treat as raw bytes
end

Prevention

When it happens

Trigger: Ruby: Puppet::Pops::Types::PBinaryType::Binary.from_string(str) where !str.valid_encoding?. Puppet DSL: Binary('...') with an argument carrying invalid bytes for its encoding — typically data that was force_encoding'd to UTF-8 upstream without being transcoded.

Common situations: Reading raw bytes from a socket/file opened without binary mode and routing them through Binary(); database or JSON strings already corrupted by a prior force_encoding; concatenating UTF-8 and binary fragments into one string.

Related errors


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