puppetlabs/puppet · error · Puppet::DevError
Could not convert change '%{name}' to string: %{detail}
Error message
Could not convert change '%{name}' to string: %{detail} What it means
When a property changes, Puppet renders the log/report message via change_to_s, which calls is_to_s and should_to_s on the current and desired values. If those helpers raise, the rescue logs the cause (Puppet.log_exception) and re-raises it as Puppet::DevError including the property name and the original detail; genuine Puppet::Error exceptions pass through unchanged. The message you see is therefore a wrapper - the real defect is whatever the detail reports.
Source
Thrown at lib/puppet/property.rb:218
# Formats a message for a property change from the given `current_value` to the given `newvalue`.
# @return [String] a message describing the property change.
# @note If called with equal values, this is reported as a change.
# @raise [Puppet::DevError] if there were issues formatting the message
#
def change_to_s(current_value, newvalue)
if current_value == :absent
"defined '#{name}' as #{should_to_s(newvalue)}"
elsif newvalue == :absent or newvalue == [:absent]
"undefined '#{name}' from #{is_to_s(current_value)}"
else
"#{name} changed #{is_to_s(current_value)} to #{should_to_s(newvalue)}"
end
rescue Puppet::Error
raise
rescue => detail
message = _("Could not convert change '%{name}' to string: %{detail}") % { name: name, detail: detail }
Puppet.log_exception(detail, message)
raise Puppet::DevError, message, detail.backtrace
end
# Produces the name of the event to use to describe a change of this property's value.
# The produced event name is either the event name configured for this property, or a generic
# event based on the name of the property with suffix `_changed`, or if the property is
# `:ensure`, the name of the resource type and one of the suffixes `_created`, `_removed`, or `_changed`.
# @return [String] the name of the event that describes the change
#
def event_name
value = should
event_name = self.class.value_option(value, :event) and return event_name
name == :ensure or return (name.to_s + "_changed").to_sym
(resource.type.to_s + case value
when :present; "_created"
when :absent; "_removed"View on GitHub (pinned to e227c27540)
Solutions
- Read the detail in the message (and the logged original exception) - it names the real failure; fix that munge/should logic.
- Make is_to_s/should_to_s defensive: coerce values with to_s/inspect instead of assuming structure.
- If you rescue inside those helpers, re-raise Puppet::Error subclasses so they are not double-wrapped.
Example fix
# before (custom property)
def should_to_s(v)
"#{v[:name]}=#{v[:value]}" # NoMethodError when v is not a Hash -> DevError wrapper
end
# after
def should_to_s(v)
v.is_a?(Hash) ? "#{v[:name]}=#{v[:value]}" : v.inspect
end Defensive patterns
Strategy: try-catch
Try / catch
msg = begin
property.change_to_s(is_value, should_value)
rescue Puppet::DevError
"#{property.name} changed #{is_value.inspect} to #{should_value.inspect}" # fallback text
end Prevention
- Keep munge/is_to_s/should_to_s total: never assume value shape, use inspect fallbacks.
- Unit-test message rendering (call change_to_s directly in property specs) so regressions surface in CI.
- Fix the 'detail' exception, not the wrapper: the DevError is only a symptom.
When it happens
Trigger: A custom property whose munge, should or should_to_s raises for a specific value; calling change_to_s during report generation when the resource has no provider; values that fail interpolation inside the message helpers.
Common situations: Third-party properties with fragile munge blocks; tooling that formats change messages outside a normal transaction; values of an unexpected class reaching message rendering.
Related errors
- Could not convert change %{name} to string: %{detail}
- Unable to connect to the server at %{uri}. Detail: %{detail}
- Supported values for Property#array_matching are 'first' and
- Attempt to redefine method %{method} with block
- Provider %{provider} must have features '%{needed_feature}'
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/0d7a617e8c33fc5f.
Report an issue: GitHub.