Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wkhtmltopdf ContentNotFoundError #19701

Open
AJM-LSC opened this issue Jan 20, 2023 · 6 comments
Open

wkhtmltopdf ContentNotFoundError #19701

AJM-LSC opened this issue Jan 20, 2023 · 6 comments
Labels

Comments

@AJM-LSC
Copy link

AJM-LSC commented Jan 20, 2023

Information about bug

When I enter a DocType and click the Print button and then click the PDF button I get the reported error.

the original error was connection refused.

Traceback (most recent call last): File "apps/frappe/frappe/app.py", line 69, in application response = frappe.api.handle() File "apps/frappe/frappe/api.py", line 54, in handle return frappe.handler.handle() File "apps/frappe/frappe/handler.py", line 45, in handle data = execute_cmd(cmd) File "apps/frappe/frappe/handler.py", line 83, in execute_cmd return frappe.call(method, **frappe.form_dict) File "apps/frappe/frappe/__init__.py", line 1595, in call return fn(*args, **newargs) File "apps/frappe/frappe/utils/print_format.py", line 129, in download_pdf pdf_file = frappe.get_print( File "apps/frappe/frappe/__init__.py", line 2028, in get_print return get_pdf(html, options=pdf_options, output=output) File "apps/frappe/frappe/utils/pdf.py", line 38, in get_pdf filedata = pdfkit.from_string(html, options=options or {}, verbose=True) File "env/lib/python3.10/site-packages/pdfkit/api.py", line 75, in from_string return r.to_pdf(output_path) File "env/lib/python3.10/site-packages/pdfkit/pdfkit.py", line 201, in to_pdf self.handle_error(exit_code, stderr) File "env/lib/python3.10/site-packages/pdfkit/pdfkit.py", line 155, in handle_error raise IOError('wkhtmltopdf reported an error:\n' + stderr) OSError: wkhtmltopdf reported an error: Exit with code 1 due to network error: ConnectionRefusedError

i added "host_name": "http://127.0.0.1", to the site_config.json suggested by a forum post that then produced the below error.

Module

selling

Version

Installed Apps
ERPNext: v14.13.0 (version-14)
Frappe Framework: v14.23.0 (version-14)
Frappe HR: v1.0.0 (develop)
Frappe LMS: v0.0.1 (main)
Payments: v0.0.1 (develop)
Wiki: v0.0.1 (master)

Installation method

docker

Relevant log output / Stack trace / Full Error Message.

Traceback (most recent call last):
  File "apps/frappe/frappe/utils/pdf.py", line 38, in get_pdf
    filedata = pdfkit.from_string(html, options=options or {}, verbose=True)
  File "env/lib/python3.10/site-packages/pdfkit/api.py", line 75, in from_string
    return r.to_pdf(output_path)
  File "env/lib/python3.10/site-packages/pdfkit/pdfkit.py", line 201, in to_pdf
    self.handle_error(exit_code, stderr)
  File "env/lib/python3.10/site-packages/pdfkit/pdfkit.py", line 155, in handle_error
    raise IOError('wkhtmltopdf reported an error:\n' + stderr)
OSError: wkhtmltopdf reported an error:
Exit with code 1 due to network error: ContentNotFoundError


During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "apps/frappe/frappe/app.py", line 69, in application
    response = frappe.api.handle()
  File "apps/frappe/frappe/api.py", line 54, in handle
    return frappe.handler.handle()
  File "apps/frappe/frappe/handler.py", line 45, in handle
    data = execute_cmd(cmd)
  File "apps/frappe/frappe/handler.py", line 83, in execute_cmd
    return frappe.call(method, **frappe.form_dict)
  File "apps/frappe/frappe/__init__.py", line 1595, in call
    return fn(*args, **newargs)
  File "apps/frappe/frappe/utils/print_format.py", line 129, in download_pdf
    pdf_file = frappe.get_print(
  File "apps/frappe/frappe/__init__.py", line 2028, in get_print
    return get_pdf(html, options=pdf_options, output=output)
  File "apps/frappe/frappe/utils/pdf.py", line 46, in get_pdf
    frappe.throw(_("PDF generation failed because of broken image links"))
  File "apps/frappe/frappe/__init__.py", line 525, in throw
    msgprint(
  File "apps/frappe/frappe/__init__.py", line 493, in msgprint
    _raise_exception()
  File "apps/frappe/frappe/__init__.py", line 442, in _raise_exception
    raise raise_exception(msg)
frappe.exceptions.ValidationError: PDF generation failed because of broken image links
@AJM-LSC AJM-LSC added the bug label Jan 20, 2023
@deepeshgarg007 deepeshgarg007 transferred this issue from frappe/erpnext Jan 20, 2023
@jugalgalaxyz
Copy link

jugalgalaxyz commented Jan 20, 2023

In addition to the host_name key, add the corresponding domain name entry to the /etc/hosts file as mentioned in the documentation here. I've mentioned the bench command below for your reference.

$ bench --site library.test add-to-hosts

@AJM-LSC
Copy link
Author

AJM-LSC commented Jan 20, 2023

thanks, @jugalgalaxyz, this might be a docker issue.

frappe@57e5bed508cb:~/frappe-bench$ bench --site 192.168.0.144 add-to-hosts

/bin/sh: 1: sudo: not found

@india081947
Copy link

india081947 commented Apr 25, 2023

Same issue was with us too,
Adding "host_name": "http://127.0.0.1" resolves the issue partly on dev machine, but as per the docs from https://wkhtmltopdf.org/usage/wkhtmltopdf.txt
as per the doc --quiet is maintained for backwards compatibility;

if we remove this option from

"quiet": None,

Then it will not give the error.

So, the question is

  1. "host_name": "http://127.0.0.1" is not being configured in docker setup by default, and if missed then creates PDF generation error. We can add it manually. Again adding this only works on local dev machine, and not on docket version on production server with multiple bench setup. This issue is not found in Version 13 with docker and multi bench version
  2. Removing --quiet from pdf options as it is only maintained for backwards compatibility as per the wkhtmltopdf docs.

Which option shall be preferred.

@india081947
Copy link

@revant thanks for the update, as we checked it, default is kept blank and configurator will add the needed settings, but in the default configuration and as per current frappe_docker if we configure the production environment via docker it just not allowing the PDF generation.

Adding "host_name": "http://127.0.0.1" in local dev machine works when there is no site(domain) name but when we do it with behind docker production(traefik / nginx) it throws frappe.exceptions.ValidationError: PDF generation failed because of broken image links.

We also tried it with adding entry in backend container /etc/hosts added with 127.0.0.1 livedomain.example.com but that too did not worked...

Problem happens due to

html = scrub_urls(html)

Where scrub_urls will expand all urls to full url with port as 8000, and because port 8000 will never be accessible from web due to behind traefik & firewall.

Finally Adding "host_name": "https://livedomain.example.com:443" has made it possible to get print working, but if we omit the port then it will add the 8000 as port in full url and from web it will not be accessible and will again throw error. Reference:

and not url_contains_port(host_name)

If I am missing something then please help, and if I have valid point then it would be great if we can add this to docker documentation, as to add host_name in site_config with port specified either 80 / 443.

@James3UK
Copy link

James3UK commented Jan 3, 2024

see also:
frappe/erpnext#35155
frappe/erpnext#35155 (comment)

wkhtmltopdf has been abandoned the last year and the repository is now archived.
Its author recommends WeasyPrint.

@mtsanovv
Copy link

In case anybody stumbles upon this issue on Windows with Docker or Podman while working on local dev with port 8080 and plain old 127.0.0,1 (personally, I'm using using Podman 4.9.4 with docker-compose 2.23 and I'm running everything with podman compose -p erpnext -f pwd.yml up -d, working directory is frappe_docker's main branch): the original error OSError: wkhtmltopdf reported an error: Exit with code 1 due to network error: ConnectionRefusedError means that the backend container cannot reach the frontend container's HTTP server (and in a local dev with pwd.yml this shouldn't be the case). The many forum posts that suggest changing the host_name to http://127.0.0.1:8000 in site_config.json are wrong because port 8000 is where the backend API HTTP service is listening in its container and this is why the error afterwards is frappe.exceptions.ValidationError: PDF generation failed because of broken image links - the backend API HTTP service simply cannot serve those assets.

Using bench leads to nowhere in this case. What's odd is that the backend container can pull things off the Internet so NAT works, it seems like there is no bridge between it and the frontend container over 127.0.0.1. The Windows machine, hosting the entire setup, can obviously reach ERPNext via http://127.0.0.1:8080. The solution is to set host_name to http://<container-name>:8080 in site_config.json. In my case, <container-name> is erpnext-frontend-1. I used nslookup & curl to make sure that the backend container can reach this URL.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants