ruby/ruby · error · Gem::OptionParser::InvalidArgument
#{key_file}: does not exist
Error message
#{key_file}: does not exist What it means
open_private_key reads the file given to -K/--key with OpenSSL::PKey.read; Errno::ENOENT is re-raised as Gem::OptionParser::InvalidArgument '<path>: does not exist'. The check runs during execute (e.g. when signing with -s or re-signing with -R), and an encrypted key additionally consults GEM_PRIVATE_KEY_PASSPHRASE.
Source
Thrown at lib/rubygems/commands/cert_command.rb:101
end
def open_cert(certificate_file)
check_openssl
OpenSSL::X509::Certificate.new File.read certificate_file
rescue Errno::ENOENT
raise Gem::OptionParser::InvalidArgument, "#{certificate_file}: does not exist"
rescue OpenSSL::X509::CertificateError
raise Gem::OptionParser::InvalidArgument,
"#{certificate_file}: invalid X509 certificate"
end
def open_private_key(key_file)
check_openssl
passphrase = ENV["GEM_PRIVATE_KEY_PASSPHRASE"]
key = OpenSSL::PKey.read File.read(key_file), passphrase
key
rescue Errno::ENOENT
raise Gem::OptionParser::InvalidArgument, "#{key_file}: does not exist"
rescue OpenSSL::PKey::PKeyError, ArgumentError
raise Gem::OptionParser::InvalidArgument, "#{key_file}: invalid RSA, DSA, or EC key"
end
def execute
check_openssl
options[:add].each do |certificate|
add_certificate certificate
end
options[:remove].each do |filter|
remove_certificates_matching filter
end
options[:list].each do |filter|
list_certificates_matching filter
endView on GitHub (pinned to 0e5b888e1c)
Solutions
- Generate a key pair if absent: gem cert --build you@example.com
- Copy the existing key to the expected path (default ~/.gem/gem-private_key.pem, mode 0600)
- Pass an absolute path to -K
Example fix
# before gem cert -K key.pem -C gem-public_cert.pem -s to_sign.pem # InvalidArgument: key.pem: does not exist # after gem cert -K "$HOME/.gem/gem-private_key.pem" -C gem-public_cert.pem -s to_sign.pem
Defensive patterns
Strategy: validation
Validate before calling
key_path = File.expand_path('gem-private_key.pem', Gem.dir)
unless File.file?(key_path)
abort 'no private key; run: gem cert --build you@example.com'
end
system('gem', 'cert', '-K', key_path, '-C', cert_path, '-R') or exit 1 Try / catch
begin
cmd.invoke
rescue Gem::OptionParser::InvalidArgument => e
raise unless e.message == "#{key_path}: does not exist"
system('gem', 'cert', '--build', email) # provision key+cert, then retry manually
end Prevention
- Check for ~/.gem/gem-private_key.pem as a provisioning step on new machines and CI
- Keep key and cert paths in variables validated once at script start
- Keep key permissions at 0600 so tooling does not skip or copy them unexpectedly
When it happens
Trigger: `gem cert -K missing.pem -C cert.pem -s to_sign.pem`; first-ever signing on a machine where gem-private_key.pem was never generated or copied; a typo'd relative path.
Common situations: New CI runners lacking the developer's private key; key stored outside the working directory; scripts assuming `gem cert --build` already ran.
Related errors
- #{key_file}: invalid RSA, DSA, or EC key
- #{cert_file}: does not exist
- #{certificate_file}: does not exist
- Private DSA key needed!
- private key needed.
AI-assisted analysis of ruby/ruby@0e5b888e1c (2026-08-21).
Data as JSON: /api/errors/0c49fc562d0253ff.
Report an issue: GitHub.