Hello,
TLDR: An update to llhttp is needed to fix an issue which causes requests from http to fail.
I recently updated to http ~> 6. After deploying, I started seeing a new exception:
TypeError: wrong argument type Hash (expected Class) parser << data ^^^^
[GEM_ROOT]/gems/http-6.0.4/lib/http/response/parser.rb#57 in HTTP::Response::Parser#add
[GEM_ROOT]/gems/http-6.0.4/lib/http/connection/internals.rb#134 in HTTP::Connection::Internals#read_more
This exception was reported about 1,000 times per day from a sidekiq process which makes around 900 http requests/second, but I don't think the issue is volume dependent. The attached reproduction triggers it with a single parser and one compaction and no concurrency.
The root cause is in llhttp's MRI C extension, not in http itself. It looks like in a long running process, garbage compaction is causing memory corruption in llhttp.
Two things make this worse than a normal exception:
- Rescuing makes it worse. The memory stays stale after the first failure, so a process which rescues the error and keeps running eventually segfaults.
- It may not always raise. An exception only occurs because the object in the slot doesn't respond to the callback method. An object that does respond would receive the response body and headers silently, with no error at all.
There's a fix available in bryanp/llhttp#40, but I thought since http is probably the largest consumer of this dependency, there are a lot of http users exposed to this issue.
I've attached a reproduction which illustrates the issue. Here are the instructions for how to get the patched version of llhttp to complete the demo:
Download demo.txt to demo
git clone https://github.com/bryanp/llhttp
gh pr diff 40 --repo bryanp/llhttp | git -C llhttp apply --include='mri/*'
ruby -C llhttp/mri/ext/llhttp extconf.rb
make -C llhttp/mri/ext/llhttp
cp llhttp/mri/ext/llhttp/llhttp_ext.$(ruby -e 'print RbConfig::CONFIG["DLEXT"]') llhttp/mri/lib/
LLHTTP_LIB=$PWD/llhttp/mri/lib ruby demo.txt
Here's the output when I run it:
LLHTTP_LIB=$PWD/llhttp/mri/lib ruby demo.txt
ruby ruby 4.0.6 (2026-07-14 revision 03b6d3f889) +PRISM [arm64-darwin25]
http 6.0.4
llhttp 0.6.2
stock llhttp /Users/ben/.rbenv/versions/4.0.6/lib/ruby/gems/4.0.0/gems/llhttp-0.6.2/lib/llhttp_ext.bundle
patched llhttp (PR #40) /Users/ben/Sites/http-error/llhttp/mri/lib/llhttp_ext.bundle
== parse: does a fresh parser survive one compaction?
stock llhttp (10 processes)
10x ❌ CRASH [BUG] Segmentation fault at 0x…
patched llhttp (PR #40) (10 processes)
10x ✅ OK parsed 10/10 after compaction
== misdispatch: what object do the callbacks actually reach?
stock llhttp (10 processes)
7x ❌ NoMethodError: undefined method 'on_header_field' for #<Object:0x…> (decoys=20000)
3x ❌ CRASH [BUG] Segmentation fault at 0x…
patched llhttp (PR #40) (10 processes)
10x ✅ OK parsed {"X-Account" => "12345", "Content-Length" => "12"}
== worker: does rescuing the error contain the damage?
stock llhttp (10 processes)
10x ❌ CRASH [BUG] Segmentation fault at 0x…
patched llhttp (PR #40) (10 processes)
10x ✅ OK survived 30 rounds
Thanks!
Hello,
TLDR: An update to
llhttpis needed to fix an issue which causes requests fromhttpto fail.I recently updated to
http ~> 6. After deploying, I started seeing a new exception:This exception was reported about 1,000 times per day from a sidekiq process which makes around 900 http requests/second, but I don't think the issue is volume dependent. The attached reproduction triggers it with a single parser and one compaction and no concurrency.
The root cause is in llhttp's MRI C extension, not in
httpitself. It looks like in a long running process, garbage compaction is causing memory corruption inllhttp.Two things make this worse than a normal exception:
There's a fix available in bryanp/llhttp#40, but I thought since
httpis probably the largest consumer of this dependency, there are a lot ofhttpusers exposed to this issue.I've attached a reproduction which illustrates the issue. Here are the instructions for how to get the patched version of
llhttpto complete the demo:Download demo.txt to demo
Here's the output when I run it:
Thanks!