postalserver/postal · error · Postal::HTTP::BlockedDestinationError
No host was given for the request
Error message
No host was given for the request
What it means
Postal::HTTP::AddressGuard is the SSRF guard every outbound HTTP request (webhook delivery to HTTPEndpoints, etc.) passes through; safe_connect_address resolves the URL host and vetted addresses are pinned onto the connection. An empty host means the parsed URL had no hostname at all, which is treated as a blocked destination (BlockedDestinationError) rather than letting Net::HTTP attempt anything.
Source
Thrown at lib/postal/http/address_guard.rb:97
def local_families
families = []
Socket.ip_address_list.each do |address|
families << :ipv4 if address.ipv4? && !address.ipv4_loopback?
families << :ipv6 if address.ipv6? && !address.ipv6_loopback? && !address.ipv6_linklocal?
end
families.uniq
end
end
# @param [String] host
def initialize(host)
@host = host.to_s
end
def safe_connect_address
if @host.empty?
raise BlockedDestinationError, "No host was given for the request"
end
addresses = resolve
if addresses.empty?
raise BlockedDestinationError, "Could not resolve '#{@host}' to any IP address"
end
# Reject the whole request if *any* resolved address is blocked. This is
# checked before the reachability filtering below so that a blocked
# destination is always reported as such, regardless of which address
# families this particular server can reach. It also defeats DNS
# responses that mix a public and a private address to slip past.
addresses.each do |address|
next unless blocked?(address)
raise BlockedDestinationError,
"Destination '#{@host}' (#{address}) is not permitted"
endView on GitHub (pinned to d038eaa8c7)
Solutions
- Fix the endpoint URL to include a scheme and hostname, e.g. https://hooks.example.com/path
- Validate at save time on the HTTPEndpoint form/model: parse with URI() and require a non-empty host
- If the URL is assembled from ENV/config, check the interpolated values are present
- Handle BlockedDestinationError where calling Postal::HTTP (it maps to result code -4) and surface it to the endpoint owner
Example fix
# before endpoint.url = params[:url] # accepts "https:///hooks" # after (model validation on the endpoint) validate :url_has_host def url_has_host parsed = URI(url.to_s) errors.add(:url, "must include a scheme and host") if parsed.host.to_s.empty? rescue URI::InvalidURIError errors.add(:url, "is not a valid URL") end
Defensive patterns
Strategy: validation
Validate before calling
# before saving an HTTPEndpoint or calling Postal::HTTP.request uri = URI(url.to_s) raise ArgumentError, "URL must include a scheme and host" if uri.host.to_s.empty?
Type guard
def http_url_with_host?(value) uri = URI(value.to_s) uri.is_a?(URI::HTTP) && !uri.host.to_s.empty? rescue URI::InvalidURIError false end
Try / catch
begin Postal::HTTP.request(...) rescue Postal::HTTP::BlockedDestinationError => e # malformed/blocked destination: fail the endpoint, tell its owner; do not retry end
Prevention
- Require scheme + host on every endpoint URL at input time (model validation, not just form placeholder)
- Never build request URLs by string concatenation with unchecked variables
- Log the exact URL (host included) when an endpoint is created for later diagnosis
- Treat BlockedDestinationError result code -4 as a permanent delivery failure, not a retryable one
When it happens
Trigger: Postal::HTTP.request (or an HTTPEndpoint delivery) with a URL whose host component is empty: 'https:///hooks', 'http://', 'example.com/path' (scheme-less, so URI parsing yields a nil/empty host), or a URL built by string interpolation where the host variable was blank.
Common situations: An HTTPEndpoint saved with a malformed URL because the create form did not require a scheme+host; ENV-based URL templates where the host variable is missing; trailing-colon or whitespace-corrupted URLs pasted into config; code building URLs by concatenation without validation.
Related errors
- Could not resolve '#{@host}' to any IP address
- Destination '#{@host}' (#{address}) is not permitted
- '#{@host}' only resolves to addresses this server cannot rea
- Invalid email address
- OIDC cannot be used unless enabled in the configuration
AI-assisted analysis of postalserver/postal@d038eaa8c7 (2026-08-21).
Data as JSON: /api/errors/d15194af42b32ebd.
Report an issue: GitHub.