{"record":{"id":"b5607bc246fbd2d0","repo":"puppetlabs/puppet","slug":"provider-provider-must-have-features-needed","errorCode":null,"errorMessage":"Provider %{provider} must have features '%{needed_feature}' to set '%{property}' to '%{value}'","messagePattern":"Provider %(.+?) must have features '%(.+?)' to set '%(.+?)' to '%(.+?)'","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/property.rb","lineNumber":595,"sourceCode":"  #\n  def unsafe_validate(value)\n    super\n    validate_features_per_value(value)\n  end\n\n  # Asserts that all required provider features are present for the given property value.\n  # @raise [ArgumentError] if a required feature is not present\n  # @return [void]\n  # @api private\n  #\n  def validate_features_per_value(value)\n    features = self.class.value_option(self.class.value_name(value), :required_features)\n    if features\n      features = Array(features)\n      needed_features = features.collect(&:to_s).join(\", \")\n      unless provider.satisfies?(features)\n        # TRANSLATORS 'Provider' refers to a Puppet provider class\n        raise ArgumentError, _(\"Provider %{provider} must have features '%{needed_features}' to set '%{property}' to '%{value}'\") %\n                             { provider: provider.class.name, needed_features: needed_features, property: self.class.name, value: value }\n      end\n    end\n  end\n\n  # @return [Object, nil] Returns the wanted _(should)_ value of this property.\n  def value\n    should\n  end\n\n  # (see #should=)\n  def value=(values)\n    self.should = values\n  end\nend\n","sourceCodeStart":577,"sourceCodeEnd":611,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/property.rb#L577-L611","documentation":"newvalue entries may declare :required_features; when the property validates a should-value it calls validate_features_per_value, which asks the resource's provider whether it satisfies those features (provider.satisfies?). If not, ArgumentError is raised naming the provider class, the required features, the property and the offending value, so the run fails instead of silently sending a request the provider cannot honour.","triggerScenarios":"A custom type declares newvalue(:mounted, :required_features => :mountable) but the selected provider does not declare has_features :mountable; provider suitability falls back to a generic provider on some hosts; the feature name changed between module versions.","commonSituations":"Provider confinement (os, commands) selecting a base provider on unexpected platforms; features declared on one provider while the manifest runs against another; modules assuming capabilities the installed provider lacks.","solutions":["Declare and implement the feature on the provider: has_features :mountable in the provider class.","Make the capable provider win suitability: check confine, commands and defaultfor on the provider.","Change the manifest not to set that value on hosts whose provider lacks the feature."],"exampleFix":"# before (provider)\nPuppet::Type.type(:mount).provide(:generic) do\n  # no has_features :mountable -> setting 'mounted' raises ArgumentError\nend\n\n# after\nPuppet::Type.type(:mount).provide(:generic) do\n  has_features :mountable\n  # ... implement mount/umount ...\nend","handlingStrategy":"validation","validationCode":"# before assigning a feature-gated value\nrequired = [:mountable]\nunless resource.provider.satisfies?(required)\n  fail \"provider #{resource.provider.class.name} lacks #{required.join(', ')}; cannot set #{value}\"\nend","typeGuard":null,"tryCatchPattern":"begin\n  property.should = value\nrescue ArgumentError => e\n  raise unless e.message =~ /must have features/\n  Puppet.warning(\"#{e.message}; skipping #{property.name}\")\nend","preventionTips":["Declare has_features on providers that implement capability-gated values.","Gate manifest values on provider capability (facts/parameters) instead of letting validation fail at apply time.","Document required features next to newvalues in custom types."],"tags":["puppet","provider","features","capability-check","custom-type"],"backgroundTag":"missing-provider-feature","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}