mileszs / wicked_pdf

PDF generator (from HTML) plugin for Ruby on Rails
http://www.mileszs.com/wicked-pdf-plugin
MIT License
3.52k stars 640 forks source link

v2.8.0 causing ActionView::Template::Error: no implicit conversion of nil into String for first time in years #1117

Open WhisperClaims opened 1 month ago

WhisperClaims commented 1 month ago

Method generate_report_pdf is causing ActionView::Template::Error: no implicit conversion of nil into String error in wicked_pdf find_asset method in Staging & Production environments on Heroku only

Expect no error in asset retrieval

System specifications

wicked_pdf (2.8.0)

wkhtmltopdf 0.12.6 (with patched qt)

wkhtmltopdf-binary (0.12.6.6) used in test / development only

Heroku-22 Stack with heroku/nodejs & heroku/ruby buildpacks

Line 6 (in bold - stylesheet_link_tag) is causing the issue

<html>
  <head>
    <meta charset='utf-8' />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    **<%= stylesheet_link_tag wicked_pdf_asset_base64("pdf") -%>**
  </head>
  <body>
    <%= render partial: "report/sections/cover", locals: { values: values, branding: branding, company: company, logo_url: logo_url } %>
  </body>
</html>

We recently updated our gemfile, including incrementing Rails 7.0.8 > 7.0.8.1 and wicked_pdf 2.7.0 > 2.8.0 which introduced the issue. PDF report generation failing as a result.

Everything works as expected if we revert to wicked_pdf (2.7.0)

Happy to supply as much more information as needed to identify the cause!

unixmonkey commented 1 month ago

This sounds like it could possibly be related to this line change and possibly fixed by https://github.com/mileszs/wicked_pdf/pull/1115

I think in 2.7.0, you would have been skipping the manifest and going straight to Sprockets to look up your asset (which I don't think is even in Rails by default anymore), but in 2.8.0, you are now dealing with the asset manifest, which is less forgiving.

I see you are using wicked_pdf_asset_base64 with the argument "pdf", but in production mode, the asset manifest fetches assets with an exact filename, like "pdf.css", not by file basename.

If you were using wicked_pdf_stylesheet_link_tag("pdf"), it can infer you want a CSS file. If you were using wicked_pdf_javascript_include_tag("pdf"), it can infer you want a JS file.

wicked_pdf_asset_base64 does not know what kind of asset you need, and thus can't add the extension to get it to resolve.

Please try adding an extension like "pdf.css", and let me know how that goes for you. If you could, please also try with that fix PR by adding this to your Gemfile:

git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gem 'wicked_pdf', github: 'd4rky-pl/wicked_pdf', branch: 'local-assets-fixes'

And let me know how it goes. I plan on merging that soon, but I'd love to know if it fixes your issue specifically, while not specifying an extension. I worry that it might still choose the wrong asset if you have both a pdf.css and pdf.js or pdf.png file, by the luck of which one the manifest has in it first.

However, I think that's reasonable. Base64 can be anything, so I think ultimately you should specify the extension as well.

Please let me know how it goes!

WhisperClaims commented 1 month ago

Amazing, tsm for the fast reply @unixmonkey. That makes perfect sense. I should be able to test that for you tomorrow

WhisperClaims commented 1 month ago

Hey @unixmonkey neither of these suggestions appear to have worked. I tried adding the file extension pdf > pdf.css and I tried adding the local-assets-fixes branch. I didn't try them together.

I'm short on time this week so happy to revert to 2.7.0 for now but it would be good to try and identify and address the issue

unixmonkey commented 1 month ago

@WhisperClaims Interesting. Before you quit, did you also add the path to the asset? Like, assuming pdf.css is in app/assets/stylesheets/pdf.css, did you try wicked_pdf_asset_base64("stylesheets/pdf.css")?

If that didn't work, and you get a minute, I'd be curious if you can run the rails console in production and run Rails.application.assets_manifest.assets and look through the hash keys returned to see what key pdf.css actually exists at.

Good luck!

WhisperClaims commented 1 month ago

No I didn't @unixmonkey - I will do asap and will report back

ceneon commented 1 month ago

I was experiencing a similar issue, and this thread was super helpful to understand what's going on.

no implicit conversion of nil into String (ActionView::Template::Error) lib/wicked_pdf/wicked_pdf_helper/assets.rb in find_asset at line 205

Curiously this not only happened in production only, but only when rendering the PDF in a Delayed Job. Requesting it live from the app worked normally.

Checking assets_manifest in a production console did the trick for me:

irb(main):002> Rails.application.assets_manifest.assets["invoice"]
=> nil
irb(main):003> Rails.application.assets_manifest.assets["invoice.css"]
=> "invoice-710f8be9e74f45a8850156564ffad56783b45d05c08e94a6a13c664390c44ff8.css"
irb(main):004> 

Thank you both :)