{"record":{"id":"0c49fc562d0253ff","repo":"ruby/ruby","slug":"key-file-does-not-exist","errorCode":null,"errorMessage":"#{key_file}: does not exist","messagePattern":"#(.+?): does not exist","errorType":"exception","errorClass":"Gem::OptionParser::InvalidArgument","httpStatus":null,"severity":"error","filePath":"lib/rubygems/commands/cert_command.rb","lineNumber":101,"sourceCode":"  end\n\n  def open_cert(certificate_file)\n    check_openssl\n    OpenSSL::X509::Certificate.new File.read certificate_file\n  rescue Errno::ENOENT\n    raise Gem::OptionParser::InvalidArgument, \"#{certificate_file}: does not exist\"\n  rescue OpenSSL::X509::CertificateError\n    raise Gem::OptionParser::InvalidArgument,\n      \"#{certificate_file}: invalid X509 certificate\"\n  end\n\n  def open_private_key(key_file)\n    check_openssl\n    passphrase = ENV[\"GEM_PRIVATE_KEY_PASSPHRASE\"]\n    key = OpenSSL::PKey.read File.read(key_file), passphrase\n    key\n  rescue Errno::ENOENT\n    raise Gem::OptionParser::InvalidArgument, \"#{key_file}: does not exist\"\n  rescue OpenSSL::PKey::PKeyError, ArgumentError\n    raise Gem::OptionParser::InvalidArgument, \"#{key_file}: invalid RSA, DSA, or EC key\"\n  end\n\n  def execute\n    check_openssl\n\n    options[:add].each do |certificate|\n      add_certificate certificate\n    end\n\n    options[:remove].each do |filter|\n      remove_certificates_matching filter\n    end\n\n    options[:list].each do |filter|\n      list_certificates_matching filter\n    end","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/ruby/ruby/blob/0e5b888e1c355f3f728f2659f085820937dada48/lib/rubygems/commands/cert_command.rb#L83-L119","documentation":"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.","triggerScenarios":"`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.","commonSituations":"New CI runners lacking the developer's private key; key stored outside the working directory; scripts assuming `gem cert --build` already ran.","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"],"exampleFix":"# before\ngem cert -K key.pem -C gem-public_cert.pem -s to_sign.pem\n# InvalidArgument: key.pem: does not exist\n\n# after\ngem cert -K \"$HOME/.gem/gem-private_key.pem\" -C gem-public_cert.pem -s to_sign.pem","handlingStrategy":"validation","validationCode":"key_path = File.expand_path('gem-private_key.pem', Gem.dir)\nunless File.file?(key_path)\n  abort 'no private key; run: gem cert --build you@example.com'\nend\nsystem('gem', 'cert', '-K', key_path, '-C', cert_path, '-R') or exit 1","typeGuard":null,"tryCatchPattern":"begin\n  cmd.invoke\nrescue Gem::OptionParser::InvalidArgument => e\n  raise unless e.message == \"#{key_path}: does not exist\"\n  system('gem', 'cert', '--build', email) # provision key+cert, then retry manually\nend","preventionTips":["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"],"tags":["rubygems","cert","private-key","file-not-found","signing"],"backgroundTag":"file-not-found","analyzedSha":"0e5b888e1c355f3f728f2659f085820937dada48","analyzedAt":"2026-08-21T14:25:43.473Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}