{"record":{"id":"b6f6f3d17f4844ad","repo":"puppetlabs/puppet","slug":"both-type-and-title-must-be-given","errorCode":null,"errorMessage":"Both type and title must be given","messagePattern":"Both type and title must be given","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/pal/json_catalog_encoder.rb","lineNumber":56,"sourceCode":"  # @return String The catalog in Json format using rich data format\n  # @api public\n  #\n  def encode\n    possibly_filtered_catalog.to_json(:pretty => pretty)\n  end\n\n  # Returns one particular resource as a Json string, or returns nil if resource was not found.\n  # @param type [String] the name of the puppet type (case independent)\n  # @param title [String] the title of the wanted resource\n  # @return [String] the resulting Json text\n  # @api public\n  #\n  def encode_resource(type, title)\n    # Ensure that both type and title are given since the underlying API will do mysterious things\n    # if 'title' is nil. (Other assertions are made by the catalog when looking up the resource).\n    #\n    # TRANSLATORS 'type' and 'title' are internal parameter names - do not translate\n    raise ArgumentError, _(\"Both type and title must be given\") if type.nil? or title.nil?\n\n    r = possibly_filtered_catalog.resource(type, title)\n    return nil if r.nil?\n\n    r.to_data_hash.to_json(:pretty => pretty)\n  end\n\n  # Applies a filter for virtual resources and returns filtered catalog\n  # or the catalog itself if filtering was not needed.\n  # The result is cached.\n  # @api private\n  # rubocop:disable Naming/MemoizedInstanceVariableName\n  def possibly_filtered_catalog\n    @filtered ||= (exclude_virtual ? catalog.filter(&:virtual?) : catalog)\n  end\n  private :possibly_filtered_catalog\n  # rubocop:enable Naming/MemoizedInstanceVariableName\nend","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/pal/json_catalog_encoder.rb#L38-L74","documentation":"Puppet::Pal::JsonCatalogEncoder#encode_resource requires both the resource type name and the title; if either is nil it raises ArgumentError before touching the catalog. The guard exists because the underlying catalog lookup behaves unpredictably when title is nil.","triggerScenarios":"encoder.encode_resource('File', nil), encode_resource(nil, 'conf'), or dynamic lookups like encode_resource(res['type'], res['title']) where a hash key is missing or misspelled and yields nil.","commonSituations":"Driving catalog-to-JSON export from user-supplied hashes or YAML where fields are optional; key typos (:tile vs :title); iterating filtered resources whose title is empty.","solutions":["Check both type and title are non-nil before calling encode_resource","Fix the data source: use fetch/default so the values are always present strings","Iterate catalog.resources and encode each instead of looking up by type/title"],"exampleFix":"# before\nencoder.encode_resource(params['type'], params['tile']) # typo -> nil\n\n# after\ntype  = params.fetch('type')\ntitle = params.fetch('title')\njson  = type && title ? encoder.encode_resource(type, title) : nil","handlingStrategy":"validation","validationCode":"return nil unless type.is_a?(String) && !type.empty? && title && !title.to_s.empty?\nencoder.encode_resource(type, title)","typeGuard":"def encodable_ref?(type, title)\n  type.is_a?(String) && !type.empty? && title.is_a?(String) && !title.empty?\nend","tryCatchPattern":null,"preventionTips":["Use fetch (not []) on option hashes so missing keys raise at the caller, not inside PAL","Skip the call when either value is nil instead of relying on the library check"],"tags":["puppet","pal","json","catalog","nil-guard"],"backgroundTag":"nil-argument","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}