bblimke/webmock · error · WebMock::NetConnectNotAllowedError
Real HTTP connections are disabled. Unregistered request: #{
Error message
Real HTTP connections are disabled. Unregistered request: #{request_signature} What it means
WebMock replaces real HTTP with registered stubs while tests run. When the Typhoeus/Hydra adapter intercepts a request whose signature matches no registered stub, and real connections are disabled (the default once WebMock is enabled via disable_net_connect!), it raises WebMock::NetConnectNotAllowedError from lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb:182. The message prints the full request signature (method, URI, headers, body) and the list of registered stubs so you can see why nothing matched. This is the tool working as designed: a test must not silently hit the live network.
Source
Thrown at lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb:182
request.block_connection = false;
::WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
if webmock_response = ::WebMock::StubRegistry.instance.response_for_request(request_signature)
# ::WebMock::HttpLibAdapters::TyphoeusAdapter.stub_typhoeus(request_signature, webmock_response, self)
response = ::WebMock::HttpLibAdapters::TyphoeusAdapter.generate_typhoeus_response(request_signature, webmock_response)
if request.respond_to?(:on_headers)
request.execute_headers_callbacks(response)
end
if request.respond_to?(:streaming?) && request.streaming?
response.options[:response_body] = "".dup
request.on_body.each { |callback| callback.call(webmock_response.body, response) }
end
request.finish(response)
webmock_response.raise_error_if_any
res = false
elsif !WebMock.net_connect_allowed?(request_signature.uri)
raise WebMock::NetConnectNotAllowedError.new(request_signature)
end
end
res
end
end
end
end
end
View on GitHub (pinned to b187df8827)
Solutions
- Read the error output: it prints the exact request signature and a ready-to-copy stub_request snippet - paste that snippet into the spec and chain .to_return(status:, body:, headers:)
- If the mismatch is subtle, diff the unregistered signature against the registered stubs listed in the message; fix query params (add them to the stub URI or .with(query: {...})), trailing slashes, or header differences
- If this request is meant to be real, open network access selectively: WebMock.disable_net_connect!(allow_localhost: true) or WebMock.disable_net_connect!(allow: ['api.example.com']), or fully with WebMock.allow_net_connect!
- If Typhoeus must not be intercepted in this suite, exclude the adapter: WebMock.disable!(except: [:typhoeus])
Example fix
// before
it 'lists users' do
Typhoeus.get('https://api.example.com/v1/users') # NetConnectNotAllowedError: unregistered request
end
// after
it 'lists users' do
stub_request(:get, 'https://api.example.com/v1/users')
.to_return(status: 200, body: '[{"id":1}]', headers: { 'Content-Type' => 'application/json' })
Typhoeus.get('https://api.example.com/v1/users')
end Defensive patterns
Strategy: validation
Validate before calling
# Before the code under test runs, assert a stub really covers the request: sig = WebMock::RequestSignature.new(:get, 'https://api.example.com/v1/users') raise 'no stub covers this request' unless WebMock.registered_request?(sig)
Try / catch
begin Typhoeus.get(url) rescue WebMock::NetConnectNotAllowedError => e WebMock.print_executed_requests # executed vs registered diff raise end
Prevention
- Register stubs in before hooks or lets that always run, never inside conditionals
- Call WebMock.print_executed_requests in your rescue to see the executed-vs-registered diff
- Use WebMock.disable_net_connect!(allow_localhost: true) or allow: [...] in suites that legitimately touch real hosts
- Stub the host broadly (stub_request(:any, %r{api\.example\.com})) so extra sub-paths still match
When it happens
Trigger: Running Typhoeus.get('https://api.example.com/v1/x') or a Typhoeus::Hydra parallel run in a spec where no stub_request(:get, 'https://api.example.com/v1/x') was registered. Also near-miss stubs: the stub omits or mismatches query params, the URI differs by trailing slash, default port or subdomain, or headers/body differ, so signature matching fails and the request counts as unregistered. Any side request the test forgot (background job, webhook callback, version-check ping) hits the same raise.
Common situations: A new endpoint was added to the client but not stubbed in the spec; spec_helper/rails_helper or another gem calls WebMock.disable_net_connect! globally; the code under test builds URLs dynamically (random ids, timestamps) so the literal stub URI never matches; the stub is registered inside a let/conditional that never runs; hitting localhost without allow_localhost: true; a dependency upgrade makes an extra telemetry request.
Related errors
- #with method invoked with no arguments. Either options hash
- The basic_auth option value should be an array which contain
- URI should be a String, Regexp, Addressable::Template, a cal
- WebMock does not support matching body for multipart/form-da
- #to_return_json does not support passing a block
AI-assisted analysis of bblimke/webmock@b187df8827 (2026-08-23).
Data as JSON: /api/errors/d2caff0c3e5f1043.
Report an issue: GitHub.