{"record":{"id":"7ec087d5ee7e7fa1","repo":"puppetlabs/puppet","slug":"modules-are-not-supported-on-dnf-versions-lower-th","errorCode":null,"errorMessage":"Modules are not supported on DNF versions lower than 3.0.1","messagePattern":"Modules are not supported on DNF versions lower than 3\\.0\\.1","errorType":"exception","errorClass":"Puppet::Error","httpStatus":null,"severity":"error","filePath":"lib/puppet/provider/package/dnfmodule.rb","lineNumber":30,"sourceCode":"require_relative '../../../puppet/provider/package'\n\nPuppet::Type.type(:package).provide :dnfmodule, :parent => :dnf do\n  has_feature :installable, :uninstallable, :versionable, :supports_flavors, :disableable\n  # has_feature :upgradeable\n  # it's not (yet) feasible to make this upgradeable since module streams don't\n  # always have matching version types (i.e. idm has streams DL1 and client,\n  # other modules have semver streams, others have string streams... we cannot\n  # programatically determine a latest version for ensure => 'latest'\n\n  commands :dnf => '/usr/bin/dnf'\n\n  def self.current_version\n    @current_version ||= dnf('--version').split.first\n  end\n\n  def self.prefetch(packages)\n    if Puppet::Util::Package.versioncmp(current_version, '3.0.1') < 0\n      raise Puppet::Error, _(\"Modules are not supported on DNF versions lower than 3.0.1\")\n    end\n\n    super\n  end\n\n  def self.instances\n    packages = []\n    cmd = \"#{command(:dnf)} module list -y -d 0 -e #{error_level}\"\n    execute(cmd).each_line do |line|\n      # select only lines with actual packages since DNF clutters the output\n      next unless line =~ /\\[[eix]\\][, ]/\n\n      line.gsub!(/\\[d\\]/, '') # we don't care about the default flag\n\n      flavor = if line.include?('[i]')\n                 line.split('[i]').first.split.last\n               else\n                 :absent","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/provider/package/dnfmodule.rb#L12-L48","documentation":"The dnfmodule provider (dnfmodule.rb:30) compares the first token of `dnf --version` against '3.0.1' during prefetch and raises Puppet::Error when versioncmp says the installed DNF is older. DNF module commands (dnf module list/install) are only reliable from 3.0.1 onwards, so on older DNF (RHEL 7 era dnf, Fedora < 27) the provider refuses to manage module packages.","triggerScenarios":"Any catalog containing a package resource handled by dnfmodule (usually ensure => installed with a module-flavored name or an explicitly selected provider => dnfmodule) on a host whose `dnf --version` reports < 3.0.1. The check runs in prefetch, so it fires even when the module resource is already in the desired state.","commonSituations":"RHEL/CentOS 7 systems with the dnf Copr installed; EL7 modules accidentally included in a shared profile that also targets EL8; container base images with an old dnf; someone setting provider => dnfmodule on an unsupported box.","solutions":["On hosts with old DNF, manage the packages with the yum/dnf providers instead: drop the module resources or pin `provider => 'yum'` for them.","Gate the module resources by OS fact, e.g. only include them when $facts['os']['release']['major'] >= '8'.","Or upgrade the platform to one shipping DNF >= 3.0.1 (EL8+) where dnfmodule is supported."],"exampleFix":"# before\npackage { 'nodejs:14': ensure => 'enabled', provider => 'dnfmodule' }\n\n# after\nif $facts['os']['release']['major'] >= '8' {\n  package { 'nodejs:14': ensure => 'enabled', provider => 'dnfmodule' }\n} else {\n  package { 'nodejs': ensure => installed, provider => 'yum' }\n}","handlingStrategy":"validation","validationCode":"# check dnf version before selecting dnfmodule\nv = `dnf --version 2>/dev/null`.split.first\nuse_module = v && Puppet::Util::Package.versioncmp(v, '3.0.1') >= 0\nfail 'dnfmodule needs dnf >= 3.0.1' unless use_module","typeGuard":"def supports_dnf_modules?(facts)\n  facts.dig('os', 'family') == 'RedHat' && facts.dig('os', 'release', 'major').to_i >= 8\nend","tryCatchPattern":"begin\n  provider.prefetch(packages)\nrescue Puppet::Error => e\n  raise unless e.message.include?('lower than 3.0.1')\n  packages.each { |p| p[:provider] = :yum if p[:provider] == :dnfmodule }\nend","preventionTips":["Select package providers from os.release.major facts in shared profiles instead of hardcoding dnfmodule.","Keep module resources in EL8+ only code paths.","Track dnf versions in your inventory so old-dnf hosts never receive module resources."],"tags":["puppet","dnf","rpm","modules","version-check"],"backgroundTag":"unsupported-tool-version","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}