puppetlabs/puppet · error · ArgumentError
'post' requires a string 'body' argument
Error message
'post' requires a string 'body' argument
What it means
Puppet::HTTP::Client#post validates that the body argument is a String and raises ArgumentError before any connection is made. Like #put, the API performs no implicit serialization; callers render payloads themselves and must also supply a Content-Type header.
Source
Thrown at lib/puppet/http/client.rb:268
end
# Submits a POST HTTP request to the given url
#
# @param [URI] url the location to submit the http request
# @param [String] body the body of the POST request
# @param [Hash] headers merged with the default headers defined by the client. The
# `Content-Type` header is required and should correspond to the type of data passed
# as the `body` argument.
# @param [Hash] params encoded and set as the url query
# @!macro request_options
#
# @yield [Puppet::HTTP::Response] if a block is given yields the response
#
# @return [Puppet::HTTP::Response] the response
#
# @api public
def post(url, body, headers: {}, params: {}, options: {}, &block)
raise ArgumentError, "'post' requires a string 'body' argument" unless body.is_a?(String)
url = encode_query(url, params)
request = Net::HTTP::Post.new(url, @default_headers.merge(headers))
request.body = body
request.content_length = body.bytesize
raise ArgumentError, "'post' requires a 'content-type' header" unless request['Content-Type']
execute_streaming(request, options: options, &block)
end
# Submits a DELETE HTTP request to the given url.
#
# @param [URI] url the location to submit the http request
# @param [Hash] headers merged with the default headers defined by the client
# @param [Hash] params encoded and set as the url query
# @!macro request_optionsView on GitHub (pinned to e227c27540)
Solutions
- Serialize first: client.post(url, JSON.generate(data), headers: { 'Content-Type' => 'application/json' }).
- Guard optional payloads so nil never reaches the call (default to '').
- Check any wrapper gems that forward bodies verbatim from older APIs.
Example fix
# before
client.post(url, { cert: csr.to_pem }, headers: { 'Content-Type' => 'text/plain' })
# after
client.post(url, csr.to_pem, headers: { 'Content-Type' => 'text/plain' }) Defensive patterns
Strategy: type-guard
Validate before calling
body = JSON.generate(data) unless body.is_a?(String)
client.post(url, body, headers: { 'Content-Type' => 'application/json' }) Type guard
string_body = ->(b) { b.is_a?(String) }
raise ArgumentError, 'body must be a String' unless string_body.call(body) Prevention
- Serialize before calling; the API never does it for you.
- Wrap optional posts so nil becomes '' or is skipped entirely.
When it happens
Trigger: client.post(url, nil, headers: ...); client.post(url, { 'name' => 'x' }, ...) with a Hash; passing a Puppet object (node, report) that older APIs accepted directly.
Common situations: Porting code from Puppet::Network::HttpPool.post or the old REST client where bodies were serialized transparently; forgetting to call .to_s/.to_json on interpolated values; posting a symbol (e.g. :undefined variable).
Related errors
- 'put' requires a string 'body' argument
- 'post' requires a string 'body' argument
- 'post' requires a 'content-type' header
- A block is required
- Could not download module: %{message}
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/b5387bc088d7d751.
Report an issue: GitHub.