socketry/falcon · warning

Unable to resolve #{hostname}!

Error message

Unable to resolve #{hostname}!

What it means

This is a Console warning, not a raised exception. The proxy environment builds a hosts hash keyed by each upstream environment's authority, but only environments defining all three keys :authority, :ssl_context and :endpoint are registered (lib/falcon/environment/proxy.rb:35-49). During the TLS handshake, OpenSSL's SNI callback (servername_cb installed by ssl_context) calls host_context with the hostname the client sent; when it is not a key in hosts, Falcon warns 'Unable to resolve <hostname>!', logs the known hostnames, and returns nil — so no per-host certificate context is selected and the handshake fails.

Source

Thrown at lib/falcon/environment/proxy.rb:64

				end
				
				return hosts
			end
			
			# Look up the host context for the given hostname, and update the socket hostname if necessary.
			# @parameter socket [OpenSSL::SSL::SSLSocket] The incoming connection.
			# @parameter hostname [String] The negotiated hostname.
			def host_context(socket, hostname)
				hosts = self.hosts
				
				if host = hosts[hostname]
					Console.debug(self){"Resolving #{hostname} -> #{host}"}
					
					socket.hostname = hostname
					
					return host.ssl_context
				else
					Console.warn(self, hosts: hosts.keys){"Unable to resolve #{hostname}!"}
					
					return nil
				end
			end
			
			# Generate an SSL context which delegates to {host_context} to multiplex based on hostname.
			def ssl_context
				@server_context ||= OpenSSL::SSL::SSLContext.new.tap do |context|
					context.servername_cb = Proc.new do |socket, hostname|
						self.host_context(socket, hostname)
					end
					
					context.session_id_context = self.ssl_session_id
					
					context.set_params(
						ciphers: ::Falcon::TLS::SERVER_CIPHERS,
						verify_mode: ::OpenSSL::SSL::VERIFY_NONE,
					)

View on GitHub (pinned to 5107b0713f)

Solutions

  1. Register the missing hostname: add an environment whose authority exactly matches the SNI name clients send (each must define authority, ssl_context and endpoint)
  2. For local tests, connect with the configured name: curl --resolve app.example.com:443:127.0.0.1 https://app.example.com/
  3. Audit Falcon::Environment::Proxy#hosts.keys and add any DNS alias as its own environment

Example fix

# before: proxy only registers authority 'app.example.com'
#   curl https://localhost/ -> Console.warn: Unable to resolve localhost!
#   host_context returns nil and the TLS handshake fails
class ProxyEnvironment
  include Falcon::Environment::Proxy

  def environments
    [app_environment] # authority 'app.example.com'
  end
end

# after: every hostname the proxy answers is registered
class ProxyEnvironment
  include Falcon::Environment::Proxy

  def environments
    [app_environment, localhost_environment]
    # authorities: 'app.example.com', 'localhost'
    # each environment defines :authority, :ssl_context and :endpoint,
    # otherwise Proxy#hosts silently skips it
  end
end
Defensive patterns

Strategy: validation

Validate before calling

# Before exposing the proxy: assert every served hostname is registered
hosts = proxy_environment.hosts # keys are exactly the SNI names answered
expected = %w[app.example.com www.app.example.com localhost]

missing = expected - hosts.keys
abort "Proxy has no host context for: #{missing.join(', ')}" unless missing.empty?

Prevention

When it happens

Trigger: A client connects with SNI 'localhost', a bare IP, or any hostname that differs from the configured authority (www.example.com vs example.com); or a proxied environment is silently excluded from hosts because it lacks one of authority/ssl_context/endpoint, so its hostname can never resolve.

Common situations: Local testing with curl https://localhost/ against a proxy configured only for the production hostname; adding a vhost but forgetting the authority or ssl_context key; extra DNS aliases or CNAMEs pointing at the proxy that were never declared as environments; monitoring probes connecting by IP without a matching SNI name.

Related errors


AI-assisted analysis of socketry/falcon@5107b0713f (2026-08-23). Data as JSON: /api/errors/f4eb0c9a0cc27942. Report an issue: GitHub.