Summary
When an upstream service returns a broken/incomplete response (e.g. due to a timeout or network interruption), response.headers can be nil. The delete method then raises NoMethodError: undefined method '[]' for nil inside an on_complete callback, which bubbles up to the caller instead of being handled gracefully.
Steps to Reproduce
- Use
faraday-http-cache with any unsafe HTTP method (POST, PUT, PATCH, DELETE)
- Have the upstream service fail in a way that produces a response with
nil headers (e.g. timeout via net-http-persistent adapter, TCP reset, or connection interruption)
- Observe the error raised from
on_complete
Backtrace
NoMethodError: undefined method '[]' for nil
url = response.headers[header]
^^^^^^^^
faraday-http-cache-2.7.0/lib/faraday/http_cache.rb:284:in `block in Faraday::HttpCache#delete'
faraday-http-cache-2.7.0/lib/faraday/http_cache.rb:283:in `Array#each'
faraday-http-cache-2.7.0/lib/faraday/http_cache.rb:283:in `Faraday::HttpCache#delete'
faraday-http-cache-2.7.0/lib/faraday/http_cache.rb:157:in `block in Faraday::HttpCache#call!'
faraday-2.14.2/lib/faraday/response.rb:46:in `Faraday::Response#on_complete'
faraday-http-cache-2.7.0/lib/faraday/http_cache.rb:156:in `Faraday::HttpCache#call!'
Root Cause
In HttpCache#delete, the code iterates over Location and Content-Location headers to invalidate cached URLs:
def delete(request, response)
headers = %w[Location Content-Location]
headers.each do |header|
url = response.headers[header] # raises if response.headers is nil
@strategy.delete(url) if url
end
@strategy.delete(request.url)
end
should_delete? returns true for any unsafe method with a non-4xx status — which includes broken responses with nil headers that result in a status of 0 or similar edge values from the adapter.
Suggested Fix
Use safe navigation to guard against nil headers:
def delete(request, response)
headers = %w[Location Content-Location]
headers.each do |header|
url = response.headers&.[](header)
@strategy.delete(url) if url
end
@strategy.delete(request.url)
end
Environment
faraday-http-cache 2.7.0 (reproduced from 2.5.1 onward, likely present since 1.0.0)
faraday 2.14.2
faraday adapter: net-http-persistent
- Ruby 3.4
- Triggered by POST requests to a slow/degraded upstream service with a short timeout (150ms)
Summary
When an upstream service returns a broken/incomplete response (e.g. due to a timeout or network interruption),
response.headerscan benil. Thedeletemethod then raisesNoMethodError: undefined method '[]' for nilinside anon_completecallback, which bubbles up to the caller instead of being handled gracefully.Steps to Reproduce
faraday-http-cachewith any unsafe HTTP method (POST,PUT,PATCH,DELETE)nilheaders (e.g. timeout vianet-http-persistentadapter, TCP reset, or connection interruption)on_completeBacktrace
Root Cause
In
HttpCache#delete, the code iterates overLocationandContent-Locationheaders to invalidate cached URLs:should_delete?returnstruefor any unsafe method with a non-4xx status — which includes broken responses withnilheaders that result in a status of0or similar edge values from the adapter.Suggested Fix
Use safe navigation to guard against
nilheaders:Environment
faraday-http-cache2.7.0 (reproduced from 2.5.1 onward, likely present since 1.0.0)faraday2.14.2faradayadapter:net-http-persistent