Sady Sady - 25 days ago 20
Ruby Question

Runtime Error (Failed to execute) PDF could not be generated wicked_pdf with wkhtmltopdf-binary

I've looked high and low on stackoverflow searching for other solutions and none of them seem to have a suitable answer. So I'll try to be as specific as possible.

We are using wicked_pdf (0.9.7) and wkhtmltopdf-binary (0.9.9.1) in a Ruby on Rails application on Ruby 2.0 and Rails 4

Our code runs locally when we clone the repository and startup the server, but when we push to production (4 nodes), it occasionally works.

This is the error we are getting:

INFO: ***************WICKED***************
Rendered application/index.pdf.haml within layouts/pdf (209.2ms)
Rendered application/_header.pdf.haml within layouts/pdf (1.5ms)
Completed 500 Internal Server Error in 3406ms
FATAL: RuntimeError(Failed to execute:\n"/opt/application/releases/5405db831e02eb2987cc06b243333776ce9c34b8ab6db3e58e93f39c3f933621/vendor/bundle/ruby/2.0.0/bin/wkhtmltopdf" -q --header-html "file:////tmp/wicked_header_pdf20131031-15836-12qkok6.html" --footer-right "[page] of [topage]" --footer-font-size 9 --margin-top 50 --encoding "UTF-8" "file:////tmp/wicked_pdf20131031-15836-b874ab.html" "/tmp/wicked_pdf_generated_file20131031-15836-1ibji4k.pdf" \nError: PDF could not be generated!\n Command Error: /usr/bin/env: ruby: No such file or directory\n)
vendor/bundle/ruby/2.0.0/gems/wicked_pdf-0.9.7/lib/wicked_pdf.rb:69:in `rescue in pdf_from_string'
vendor/bundle/ruby/2.0.0/gems/wicked_pdf-0.9.7/lib/wicked_pdf.rb:73:in `pdf_from_string'
vendor/bundle/ruby/2.0.0/gems/wicked_pdf-0.9.7/lib/pdf_helper.rb:63:in `make_pdf'
vendor/bundle/ruby/2.0.0/gems/wicked_pdf-0.9.7/lib/pdf_helper.rb:76:in `make_and_send_pdf'
vendor/bundle/ruby/2.0.0/gems/wicked_pdf-0.9.7/lib/pdf_helper.rb:21:in `render_with_wicked_pdf'


Here is the relevant code within the application:

Gemfile

gem 'wicked_pdf', '~> 0.9.7'
gem 'wkhtmltopdf-binary', '~> 0.9.9'


Gemfile.lock

wicked_pdf (0.9.7)
rails
wkhtmltopdf-binary (0.9.9.1)


controller.rb

def show
render pdf: file_name,
layout: 'pdf',
margin: {
top: 30
},
header: {
html: {
template: '_header.pdf.haml'
}
},
footer: {
right: I18n.t('pdf.page_description'),
font_size: 9
},
encoding: 'UTF-8'
end



  • We've run (successfully) the wkhtmltopdf using bundle exec directly on the server, but when we hit the page, it will error out 500 about 3/4 of the time.

  • We've also run it in rails console with success.

  • We have used the basic wkhtmltopdf to generate a pdf from a webpage.

  • We are currently working on generating a pdf from a local file where wicked_pdf would write a temp file and trying to generate the file from there.



Any input would be gratefully appreciated.

Answer

The issue was that wkhtmltopdf was executing a shell script to determine the version of the binary to use which failed because apache has no shell (and for good reason). The solution was to set the binary explicitly.

Since our dev, staging, and prod environments vary, we created a RBConfig script that is executed within the rails app (no shell access necessary):

require 'rbconfig'

if RbConfig::CONFIG['host_os'] =~ /linux/
  arch = RbConfig::CONFIG['host_cpu'] == 'x86_64' ? 'wkhtmltopdf_linux_x64' : 'wkhtmltopdf_linux_386'
elsif RbConfig::CONFIG['host_os'] =~ /darwin/
  arch = 'wkhtmltopdf_darwin_386'
else
  raise "Invalid platform. Must be running Intel-based Linux or OSX."
end

WickedPdf.config = {
  exe_path: "#{ENV['GEM_HOME']}/gems/wkhtmltopdf-binary-#{Gem.loaded_specs['wkhtmltopdf-binary'].version}/bin/#{arch}"
}

There are several other ways to do this. For example, developing locally, your user should have shell access, in which case you really only need to set the binary explicitly for your production environment:

if Rails.env.production?
    WickedPdf.config = { ... }
end

Or, as we have done, set up our chef configuration to set up all of our environments with the proper binaries. It also let us make sure all the fonts that we need were installed for production.

Comments