puppetlabs/puppet · error · Puppet::Network::HTTP::Error::HTTPBadRequestError
The request body is invalid: %{message}
Error message
The request body is invalid: %{message} What it means
For PUT/POST requests the handler deserializes the body with model_class.convert_from using the format derived from the Content-Type header. Any exception raised during that conversion is wrapped into HTTP 400 'The request body is invalid: <original message>'. The underlying parser message is preserved, so the actual cause (bad JSON, wrong schema, truncated body) is visible in the response.
Source
Thrown at lib/puppet/network/http/api/indirected_routes.rb:228
def accepted_response_formatters_for(model_class, request)
request.response_formatters_for(model_class.supported_formats)
end
# Return the first response formatter that the client accepts and
# the server supports, or default to 'application/json'.
def accepted_response_formatter_or_json_for(model_class, request)
request.response_formatters_for(model_class.supported_formats, "application/json").first
end
def read_body_into_model(model_class, request)
data = request.body.to_s
formatter = request.formatter
if formatter.supported?(model_class)
begin
return model_class.convert_from(formatter.name.to_s, data)
rescue => e
raise Puppet::Network::HTTP::Error::HTTPBadRequestError, _("The request body is invalid: %{message}") % { message: e.message }
end
end
# TRANSLATORS "mime-type" is a keyword and should not be translated
raise Puppet::Network::HTTP::Error::HTTPUnsupportedMediaTypeError.new(
_("Client sent a mime-type (%{header}) that doesn't correspond to a format we support") % { header: request.headers['content-type'] },
Puppet::Network::HTTP::Issues::UNSUPPORTED_MEDIA_TYPE
)
end
def indirection_method(http_method, indirection)
raise Puppet::Network::HTTP::Error::HTTPMethodNotAllowedError, _("No support for http method %{http_method}") % { http_method: http_method } unless METHOD_MAP[http_method]
method = METHOD_MAP[http_method][plurality(indirection)]
unless method
raise Puppet::Network::HTTP::Error::HTTPBadRequestError, _("No support for plurality %{indirection} for %{http_method} operations") % { indirection: plurality(indirection), http_method: http_method }
end
View on GitHub (pinned to e227c27540)
Solutions
- Capture the exact body sent and validate it locally (JSON.parse or the format's convert_from) to locate the malformed part
- Ensure the Content-Type header matches the actual body format (application/json for JSON)
- Align agent and server versions, or adjust the payload to the schema the server expects
- Check body size limits in intermediate proxies if bodies arrive truncated
Example fix
# before: submitting invalid JSON
curl -X PUT -H 'Content-Type: application/json' \
-d '{ "name": "mynode", ' \
"https://puppet:8140/puppet/v3/report/mynode?environment=production"
# after: valid, complete JSON document sent from a file
curl -X PUT -H 'Content-Type: application/json' \
-d @report.json \
"https://puppet:8140/puppet/v3/report/mynode?environment=production" Defensive patterns
Strategy: try-catch
Validate before calling
require 'json'
payload = report.to_json
JSON.parse(payload) # raises now, with our own context, instead of server-side
client.put("/puppet/v3/report/#{certname}", body: payload,
headers: { 'Content-Type' => 'application/json' },
params: { environment: env }) Try / catch
begin
client.put("/puppet/v3/report/#{certname}",
body: payload,
headers: { 'Content-Type' => 'application/json' },
params: { environment: env })
rescue Puppet::Network::HTTP::Error::HTTPBadRequestError => e
# e.message carries the underlying parse error, e.g. 'The request body is invalid: unexpected token'
raise "report rejected for #{certname}: #{e.message}"
end Prevention
- Round-trip serialized output through the parser (JSON.parse) before sending
- Always send an explicit Content-Type matching the body
- Keep an integration test that submits the exact payload your tooling produces
When it happens
Trigger: PUT /puppet/v3/report/mynode with malformed JSON; submitting facts whose payload does not match the expected model schema; a Content-Type header claiming a format the body is not; truncated bodies from proxy timeouts; agent/server version skew where the payload schema differs.
Common situations: Custom report or fact submitters that hand-roll JSON; agent and server versions out of step so new fields are rejected; load balancers or proxies truncating large catalog/report bodies.
Related errors
- The indirection name must be purely alphanumeric, not '%{ind
- Indirection '%{indirection_name}' does not match url prefix
- An environment parameter must be specified
- No request key specified in %{uri}
- No support for plurality %{indirection} for %{http_method} o
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/c3775c39faafc44e.
Report an issue: GitHub.