Skip to content

LoadError when requiring native extension with require_relative in Parser.rb #33

@Annih

Description

@Annih

Environment

  • OS: Rocky Linux 8.10
  • Ruby: 3.1.4, rubygems 3.3.26
  • Gems: bundler 2.4.22, lhttp 0.6.1

Problem

The gem currently uses require_relative "../llhttp_ext" to load its native extension (See source). This causes below LoadError:

LoadError:
  cannot load such file -- /app/bundle/ruby/3.1.0/gems/llhttp-0.5.0/lib/llhttp_ext
# ./bundle/ruby/3.1.0/gems/llhttp-0.5.0/lib/llhttp/parser.rb:52:in `require_relative'
# ./bundle/ruby/3.1.0/gems/llhttp-0.5.0/lib/llhttp/parser.rb:52:in `<top (required)>'
# ./bundle/ruby/3.1.0/gems/llhttp-0.5.0/lib/llhttp.rb:6:in `require_relative'
# ./bundle/ruby/3.1.0/gems/llhttp-0.5.0/lib/llhttp.rb:6:in `<module:LLHttp>'
# ./bundle/ruby/3.1.0/gems/llhttp-0.5.0/lib/llhttp.rb:3:in `<top (required)>'
# ./bundle/ruby/3.1.0/gems/http-5.3.0/lib/http/response/parser.rb:3:in `require'

ℹ In our case, we run the app using bundle exec <app> after performing bundle install --standalone!

Reproduction Steps

  1. Add llhttp to your Gemfile.
  2. Run bundle install --standalone.
  3. Attempt to load the gem with bundle exec <app>.
  4. Observe the LoadError.

Analysis

In some environments, such as when using Bundler's --standalone mode, the extension may not be located relative to the Ruby file.
Here the require_relative expects the extension to be in /app/bundle/ruby/3.1.0/gems/llhttp-0.5.0/lib while it is actually in /app/bundle/ruby/3.1.0/gems/llhttp-0.5.0/ext/llhttp/.

Suggested Solution

Switching from require_relative "../llhttp_ext" to require "llhttp_ext" would load the extension from the $LOAD_PATH, which is the standard and recommended approach for gems with native extensions.
This would improve compatibility with Bundler and RubyGems, especially in standalone or custom deployment setups.

Reference: RubyGems Guides: Gems with Extensions

"If you have an extension you do not need to add 'ext' to the require path, the extension build process will copy the extension files into 'lib' for you. The default value is 'lib'."

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions