puppetlabs/puppet · error · Puppet::HTTP::ProtocolError
No content type in http response; cannot parse
Error message
No content type in http response; cannot parse
What it means
All Puppet::HTTP::Service subclasses (CA, fileserver, compiler, report) pick a deserializer for a response from its Content-Type header via formatter_for_response. A 2xx response with no Content-Type cannot be mapped to any format, so Puppet::HTTP::ProtocolError is raised before body parsing.
Source
Thrown at lib/puppet/http/service.rb:132
end
end
modified_headers
end
def build_url(api, server, port)
URI::HTTPS.build(host: server,
port: port,
path: api).freeze
end
def get_mime_types(model)
network_formats = model.supported_formats - EXCLUDED_FORMATS
network_formats.map { |f| model.get_format(f).mime }
end
def formatter_for_response(response)
header = response['Content-Type']
raise Puppet::HTTP::ProtocolError, _("No content type in http response; cannot parse") unless header
header.gsub!(/\s*;.*$/, '') # strip any charset
formatter = Puppet::Network::FormatHandler.mime(header)
raise Puppet::HTTP::ProtocolError, "Content-Type is unsupported" if EXCLUDED_FORMATS.include?(formatter.name)
formatter
end
def serialize(formatter, object)
formatter.render(object)
rescue => err
raise Puppet::HTTP::SerializationError.new("Failed to serialize #{object.class} to #{formatter.name}: #{err.message}", err)
end
def serialize_multiple(formatter, object)
formatter.render_multiple(object)
rescue => errView on GitHub (pinned to e227c27540)
Solutions
- Reproduce with curl -i <url> and confirm the missing header at the client's vantage point.
- Fix the origin/proxy to send the correct type (application/json, application/vnd.puppet.pson+json, etc.).
- Verify the URL actually targets a puppet route (e.g. /puppet/v3/...) and the right port (8140).
- For custom puppetserver endpoints, set response content type explicitly in the Ruby handler.
Example fix
# custom puppetserver route - before
get '/custom/status' do |req, res|
res.body = '{}'
end
# after
get '/custom/status' do |req, res|
res['Content-Type'] = 'application/json'
res.body = '{}'
end Defensive patterns
Strategy: try-catch
Try / catch
begin
service.get_cert(name)
rescue Puppet::HTTP::ProtocolError => e
raise unless e.message.include?('No content type')
# dump headers for diagnosis; likely wrong route or header-stripping proxy
raise
end Prevention
- curl -i the endpoint from the client host to verify Content-Type end-to-end.
- Custom puppetserver routes must set Content-Type explicitly.
- Point clients at puppet routes on port 8140, not auxiliary web services.
When it happens
Trigger: The server (or a proxy in front of it) replies 200 with a body but no Content-Type; a middleware/gateway stripping the header; hitting a plain HTTP port or health-check handler with a puppet path so the reply lacks puppet headers.
Common situations: Custom route handlers on puppetserver that omit content_type; misconfigured nginx/ATS proxying that drops the header; DNS/port mistakes landing on an unrelated web service that answers 200 bare.
Related errors
- Content-Type is unsupported
- 'put' requires a 'content-type' header
- 'post' requires a 'content-type' header
- Location response header is missing
- A block is required
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/e912a31049ad634c.
Report an issue: GitHub.