{"record":{"id":"30ece2c403b8cd93","repo":"puppetlabs/puppet","slug":"could-not-convert-change-name-to-string-deta","errorCode":null,"errorMessage":"Could not convert change %{name} to string: %{detail}","messagePattern":"Could not convert change %(.+?) to string: %(.+?)","errorType":"exception","errorClass":"Puppet::DevError","httpStatus":null,"severity":"error","filePath":"lib/puppet/property/ensure.rb","lineNumber":65,"sourceCode":"\n  def self.inherited(sub)\n    # Add in the two properties that everyone will have.\n    sub.class_eval do\n    end\n  end\n\n  def change_to_s(currentvalue, newvalue)\n    if currentvalue == :absent || currentvalue.nil?\n      _(\"created\")\n    elsif newvalue == :absent\n      _(\"removed\")\n    else\n      _('%{name} changed %{is} to %{should}') % { name: name, is: is_to_s(currentvalue), should: should_to_s(newvalue) }\n    end\n  rescue Puppet::Error\n    raise\n  rescue => detail\n    raise Puppet::DevError, _(\"Could not convert change %{name} to string: %{detail}\") % { name: name, detail: detail }, detail.backtrace\n  end\n\n  # Retrieves the _is_ value for the ensure property.\n  # The existence of the resource is checked by first consulting the provider (if it responds to\n  # `:exists`), and secondly the resource. A a value of `:present` or `:absent` is returned\n  # depending on if the managed entity exists or not.\n  #\n  # @return [Symbol] a value of `:present` or `:absent` depending on if it exists or not\n  # @raise [Puppet::DevError] if neither the provider nor the resource responds to `:exists`\n  #\n  def retrieve\n    # XXX This is a problem -- whether the object exists or not often\n    # depends on the results of other properties, yet we're the first property\n    # to get checked, which means that those other properties do not have\n    # @is values set.  This seems to be the source of quite a few bugs,\n    # although they're mostly logging bugs, not functional ones.\n    prov = @resource.provider\n    if prov && prov.respond_to?(:exists?)","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/property/ensure.rb#L47-L83","documentation":"Property::Ensure#change_to_s formats 'created', 'removed' or '<name> changed <is> to <should>' for the ensure property. If is_to_s or should_to_s raise while formatting, the error is re-raised as Puppet::DevError with the property name and the underlying detail - the same pattern as Property#change_to_s, but without logging the cause first. Custom ensure enumerations (mounted, purged, latest...) are the usual source.","triggerScenarios":"A custom type's ensure property supports values whose munge or *_to_s helper raises; reporting tooling calls change_to_s with values that never occur during normal syncing; should_to_s dereferences provider state while no provider is present.","commonSituations":"Custom ensure values with sloppy munges; report parsers or tools that render change messages for arbitrary catalogs.","solutions":["Fix the helper named in the detail (munge, is_to_s or should_to_s) so it handles the failing value.","Coerce defensively: fall back to inspect for values of unknown shape.","Re-raise Puppet::Error subclasses from helpers so they are not wrapped."],"exampleFix":"# before (custom type ensure)\ndef should_to_s(v)\n  v.split('=').last    # NoMethodError for symbols -> DevError wrapper\nend\n\n# after\ndef should_to_s(v)\n  v.respond_to?(:split) ? v.split('=').last.to_s : v.inspect\nend","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"msg = begin\n  ensure_prop.change_to_s(is_value, should_value)\nrescue Puppet::DevError\n  \"ensure #{is_value.inspect} -> #{should_value.inspect}\"   # fallback text\nend","preventionTips":["Cover every custom ensure value in munge/is_to_s/should_to_s; test message rendering directly.","Use inspect fallbacks for values of unknown shape.","Treat the detail as the real error; the DevError is a wrapper around it."],"tags":["puppet","ensure","logging","message-formatting","custom-type"],"backgroundTag":"to-string-conversion-failed","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}