{"record":{"id":"3317f19f5496cab8","repo":"puppetlabs/puppet","slug":"no-attr-module-metadata-provided-for-name","errorCode":null,"errorMessage":"No #{attr} module metadata provided for #{name}","messagePattern":"No #(.+?) module metadata provided for #(.+?)","errorType":"exception","errorClass":"MissingMetadata","httpStatus":null,"severity":"error","filePath":"lib/puppet/module.rb","lineNumber":253,"sourceCode":"    when :warning\n      Puppet.warning(msg)\n    when :error\n      raise FaultyMetadata, msg\n    end\n    {}\n  end\n\n  def load_metadata\n    return if instance_variable_defined?(:@metadata)\n\n    @metadata = data = read_metadata\n    return if data.empty?\n\n    @forge_name = data['name'].tr('-', '/') if data['name']\n\n    [:source, :author, :version, :license, :dependencies].each do |attr|\n      value = data[attr.to_s]\n      raise MissingMetadata, \"No #{attr} module metadata provided for #{name}\" if value.nil?\n\n      if attr == :dependencies\n        unless value.is_a?(Array)\n          raise MissingMetadata, \"The value for the key dependencies in the file metadata.json of the module #{name} must be an array, not: '#{value}'\"\n        end\n\n        value.each do |dep|\n          name = dep['name']\n          dep['name'] = name.tr('-', '/') unless name.nil?\n          dep['version_requirement'] ||= '>= 0.0.0'\n        end\n      end\n\n      send(attr.to_s + \"=\", value)\n    end\n  end\n\n  # Return the list of manifests matching the given glob pattern,","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/module.rb#L235-L271","documentation":"Puppet::Module#load_metadata walks the five required keys — source, author, version, license, dependencies — and raises Puppet::Module::MissingMetadata when any value is nil (lib/puppet/module.rb:253). Unlike the malformed-JSON case, this always raises regardless of the `strict` setting. Empty strings pass (only nil fails), but a missing, null, or misnamed key aborts module loading.","triggerScenarios":"metadata.json containing only name/version; a key explicitly set to JSON null; misspellings like 'licence' or 'authors' that leave the expected key nil.","commonSituations":"Hand-written minimal metadata for internal modules; metadata written by tooling unfamiliar with Forge conventions; refactoring that drops a key.","solutions":["Add all five keys with real values: source, author, version, license, dependencies (dependencies may be an empty array)","Use exact spellings: `license` (US spelling), `author` (singular)","Generate the file with pdk or `puppet module generate` and fill in the template"],"exampleFix":"// before (metadata.json)\n{\n  \"name\": \"acme-web\",\n  \"version\": \"1.0.0\"\n}\n\n// after\n{\n  \"name\": \"acme-web\",\n  \"version\": \"1.0.0\",\n  \"author\": \"acme\",\n  \"license\": \"Apache-2.0\",\n  \"source\": \"https://github.com/acme/puppet-web\",\n  \"dependencies\": []\n}","handlingStrategy":"try-catch","validationCode":"required = %w[source author version license dependencies]\ndata = Puppet::Util::Json.load(File.read('metadata.json'))\nmissing = required.select { |k| data[k].nil? }\nraise ArgumentError, \"metadata.json missing: #{missing.join(', ')}\" unless missing.empty?","typeGuard":null,"tryCatchPattern":"begin\n  mod = Puppet::Module.find(name, environment)\n  mod.load_metadata if mod\nrescue Puppet::Module::MissingMetadata => e\n  Puppet.warning(\"module #{name}: #{e.message}\")\n  next\nend","preventionTips":["Emit all five required keys (source, author, version, license, dependencies) in every metadata.json","Spell keys exactly: `license` (US spelling), `author` (singular)","Validate metadata completeness with pdk or metadata-json-lint before publishing"],"tags":["puppet","module","metadata","validation"],"backgroundTag":"missing-required-metadata-field","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}