{"record":{"id":"54b5e329819aaa1d","repo":"puppetlabs/puppet","slug":"field-data-provider-must-be-a-string","errorCode":null,"errorMessage":"field 'data_provider' must be a string","messagePattern":"field 'data_provider' must be a string","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/module_tool/metadata.rb","lineNumber":216,"sourceCode":"      raise ArgumentError, _(\"Invalid 'version' field in metadata.json: %{err}\") % { err: err }\n    end\n\n    # Validates that the given _value_ is a symbolic name that starts with a letter\n    # and then contains only letters, digits, or underscore. Will raise an ArgumentError\n    # if that's not the case.\n    #\n    # @param value [Object] The value to be tested\n    def validate_data_provider(value)\n      if value.is_a?(String)\n        unless value =~ /^[a-zA-Z][a-zA-Z0-9_]*$/\n          if value =~ /^[a-zA-Z]/\n            raise ArgumentError, _(\"field 'data_provider' contains non-alphanumeric characters\")\n          else\n            raise ArgumentError, _(\"field 'data_provider' must begin with a letter\")\n          end\n        end\n      else\n        raise ArgumentError, _(\"field 'data_provider' must be a string\")\n      end\n    end\n\n    # Validates that the version range can be parsed by Semantic.\n    def validate_version_range(version_range)\n      SemanticPuppet::VersionRange.parse(version_range)\n    rescue ArgumentError => e\n      raise ArgumentError, _(\"Invalid 'version_range' field in metadata.json: %{err}\") % { err: e }\n    end\n  end\nend\n","sourceCodeStart":198,"sourceCodeEnd":228,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/module_tool/metadata.rb#L198-L228","documentation":"The non-String branch of Puppet::ModuleTool::Metadata#validate_data_provider: the legacy 'data_provider' field in metadata.json must be a string, and anything else — number, boolean, array, object, null-as-value — raises ArgumentError at line 216. It is a type check rather than a format check.","triggerScenarios":"A metadata.json containing \"data_provider\": 42, \"data_provider\": true, or \"data_provider\": [\"hiera\"] — the is_a?(String) test fails and line 216 raises.","commonSituations":"Generator templates interpolating a Ruby symbol or integer unquoted into JSON; YAML config reused as JSON with unquoted values; copy-paste from documentation showing enum-like values.","solutions":["Quote the value so it is a JSON string: \"data_provider\": \"hiera\"","If the field is meaningless for your module, delete it","Lint the file: `python -m json.tool metadata.json` or a JSON schema validator to catch type mistakes"],"exampleFix":"// before - metadata.json\n\"data_provider\": 42,\n\n// after\n\"data_provider\": \"hiera\",","handlingStrategy":"type-guard","validationCode":"value = JSON.parse(File.read('metadata.json'))['data_provider']\nabort \"data_provider must be a string, got #{value.class}\" unless value.nil? || value.is_a?(String)","typeGuard":"# Ruby predicate acting as a type guard before parsing\nmodule_provider_string?(v) = v.is_a?(String) && v.match?(/\\A[a-zA-Z][a-zA-Z0-9_]*\\Z/)\n\n# usage\nraise ArgumentError, 'data_provider must be a string' unless module_data_provider.nil? || module_provider_string?(module_data_provider)","tryCatchPattern":"begin\n  Puppet::ModuleTool::Metadata.from_hash('data_provider' => raw)\nrescue ArgumentError => e\n  raise unless e.message =~ /data_provider.*must be a string/\n  raw = raw.to_s  # coerce numbers/booleans from loose templates, then retry\n  retry\nend","preventionTips":["Quote data_provider values in JSON templates; never interpolate unquoted Ruby values","Parse with strict JSON tooling (python -m json.tool, jq) to catch type mistakes early","Omit the field if the module does not use a custom data provider"],"tags":["puppet","module-tool","metadata","data-provider","type-error","validation"],"backgroundTag":"invalid-metadata-field","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}