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

Unable to Generate or Preview Invoices - Page Stuck in Loading Stat #384

Open
Venkateshvenki404224 opened this issue Dec 27, 2024 · 9 comments

Comments

@Venkateshvenki404224
Copy link

Venkateshvenki404224 commented Dec 27, 2024

I am facing an issue while generating and previewing invoices in Frappe. Whenever I try to generate an invoice that is designed using print designer or access the preview, the page enters a loading state and eventually shows an error. However, the error logs do not display any related information, making it difficult to debug the issue.

Sna.mp4

image_2024-12-27_11-32-00

image

I am using Print Designer Version:

print_designer 1.2.0
UnexpectedResponseException {message: 'Unexpected server response (504) while retrieving …A-FEE-06047&format=Student+Tax+Invoice&_lang=en".', name: 'UnexpectedResponseException', status: 504, stack: 'Error\n    at BaseExceptionClosure (<anonymous>:22:…/frappe/dist/js/desk.bundle.E7M7U3SJ.js:274:2456)'}
message
: 
"Unexpected server response (504) while retrieving PDF \"https://portal.selfmade.ninja/api/method/frappe.utils.print_format.download_pdf?doctype=Fees&name=SNA-FEE-06047&format=Student+Tax+Invoice&_lang=en\"."
name
: 
"UnexpectedResponseException"
status
: 
504
stack
: 
"Error\n    at BaseExceptionClosure (<anonymous>:22:9061)\n    at Array.<anonymous> (<anonymous>:22:9132)\n    at __w_pdfjs_require__ (<anonymous>:22:363969)\n    at <anonymous>:22:368173\n    at <anonymous>:22:368440\n    at <anonymous>:22:368471\n    at webpackUniversalModuleDefinition (<anonymous>:22:290)\n    at <anonymous>:22:294\n    at Object.eval (https://portal.selfmade.ninja/assets/frappe/dist/js/desk.bundle.E7M7U3SJ.js:294:1433)\n    at Object.js (https://portal.selfmade.ninja/assets/frappe/dist/js/desk.bundle.E7M7U3SJ.js:274:2456)"
[[Prototype]]
: 
Error
constructor
: 
class UnexpectedResponseException
stack
: 
"Error\n    at BaseExceptionClosure (<anonymous>:22:9061)\n    at Array.<anonymous> (<anonymous>:22:9132)\n    at __w_pdfjs_require__ (<anonymous>:22:363969)\n    at <anonymous>:22:368173\n    at <anonymous>:22:368440\n    at <anonymous>:22:368471\n    at webpackUniversalModuleDefinition (<anonymous>:22:290)\n    at <anonymous>:22:294\n    at Object.eval (https://portal.selfmade.ninja/assets/frappe/dist/js/desk.bundle.E7M7U3SJ.js:294:1433)\n    at Object.js (https://portal.selfmade.ninja/assets/frappe/dist/js/desk.bundle.E7M7U3SJ.js:274:2456)"
[[Prototype]]
: 
Error at BaseExceptionClosure (<anonymous>:22:9061) at Array.<anonymous> (<anonymous>:22:9132) at __w_pdfjs_require__ (<anonymous>:22:363969) at <anonymous>:22:368173 at <anonymous>:22:368440 at <anonymous>:22:368471 at webpackUniversalModuleDefinition (<anonymous>:22:290) at <anonymous>:22:294 at Object.eval (https://portal.selfmade.ninja/assets/frappe/dist/js/desk.bundle.E7M7U3SJ.js:294:1433) at Object.js (https://portal.selfmade.ninja/assets/frappe/dist/js/desk.bundle.E7M7U3SJ.js:274:2456)

The api request for generating the pdf is getting failed :

I would appreciate any guidance on how to troubleshoot or resolve this issue. Is there a way to enable more detailed logging to capture what’s going wrong? Or are there known issues or fixes for this behavior in the current version?

Thank you for your support!

@RaySolo
Copy link

RaySolo commented Dec 28, 2024

I get the same error message. The LOG says that I cannot access the .jpg because it does not exist. but that is not true. the file exists, the user and access rights are also correct.

Traceback with variables (most recent call last):
File "apps/frappe/frappe/core/doctype/file/utils.py", line 372, in attach_files_to_document
file.insert(ignore_permissions=True)
doc = <PDPrintFormat: PD SalesOrder V143.1>
event = 'on_update'
attach_fields = []
df =
value = '/private/files/print_designer-pd_salesorder_v143.1-preview.jpg'
unattached_file = None
file = <File: unsaved>
File "apps/frappe/frappe/model/document.py", line 289, in insert
self.run_method("before_insert")
self = <File: unsaved>
ignore_permissions = True
ignore_links = None
ignore_if_duplicate = False
ignore_mandatory = None
set_name = None
set_child_names = True
File "apps/frappe/frappe/model/document.py", line 974, in run_method
out = Document.hook(fn)(self, *args, **kwargs)
self = <File: unsaved>
method = 'before_insert'
args = ()
kwargs = {}
fn = <function Document.run_method..fn at 0x79fbf6359d00>
File "apps/frappe/frappe/model/document.py", line 1334, in composer
return composed(self, method, args, **kwargs)
self = <File: unsaved>
args = ()
kwargs = {}
hooks = []
method = 'before_insert'
doc_events = {'
': {'on_update': ['frappe.desk.notifications.clear_doctype_notifications', 'frappe.workflow.doctype.workflow_action.workflow_action.process_workflow_actions', 'frappe.core.doctype.file.utils.attach_files_to_document', 'frappe.automation.doctype.assignment_rule.assignment_rule.apply', 'frappe.automation.doctype.assignment_rule.assignment_rule.update_due_date', 'frappe.core.doctype.user_type.user_type.apply_permissions_for_non_standard_user_type'], 'after_rename': ['frappe.desk.notifications.clear_doctype_notifications'], 'on_cancel': ['frappe.desk.notifications.clear_doctype_notifications', 'frappe.workflow.doctype.workflow_action.workflow_action.process_workflow_actions', 'frappe.automation.doctype.assignment_rule.assignment_rule.apply'], 'on_trash': ['frappe.desk.notifications.clear_doctype_notifications', 'frappe.workflow.doctype.workflow_action.workflow_action.process_workflow_actions'], 'on_update_after_submit': ['frappe.workflow.doctype.workflow_action.workflow_action.process_w...
composed = <function Document.hook..compose..runner at 0x79fbf6359940>
compose = <function Document.hook..compose at 0x79fbf6358f40>
f = <function Document.run_method..fn at 0x79fbf6359d00>
File "apps/frappe/frappe/model/document.py", line 1316, in runner
add_to_return_value(self, fn(self, *args, **kwargs))
self = <File: unsaved>
method = 'before_insert'
args = ()
kwargs = {}
add_to_return_value = <function Document.hook..add_to_return_value at 0x79fbf6359da0>
fn = <function Document.run_method..fn at 0x79fbf6359d00>
hooks = ()
File "apps/frappe/frappe/model/document.py", line 971, in fn
return method_object(*args, **kwargs)
self = <File: unsaved>
args = ()
kwargs = {}
method_object = <bound method File.before_insert of <File: unsaved>>
method = 'before_insert'
File "apps/frappe/frappe/core/doctype/file/file.py", line 104, in before_insert
self.save_file(content=self.get_content())
self = <File: unsaved>
File "apps/frappe/frappe/core/doctype/file/file.py", line 539, in get_content
with open(file_path, mode="rb") as f:
self = <File: unsaved>
file_path = './erpdev.lan/private/files/print_designer-pd_salesorder_v143.1-preview.jpg'
builtins.FileNotFoundError: [Errno 2] No such file or directory: './erpdev.lan/private/files/print_designer-pd_salesorder_v143.1-preview.jpg'

@MiDOZ
Copy link

MiDOZ commented Jan 13, 2025

I have got the same issue, the file does not exist for me tho, here is the stack trace:
Traceback with variables (most recent call last): File "apps/frappe/frappe/core/doctype/file/utils.py", line 372, in attach_files_to_document file.insert(ignore_permissions=True) doc = <PDPrintFormat: Sales Order PD v2> event = 'on_update' attach_fields = [<Attach ImageDocField: print_designer_preview_img parent=Print Format>] df = <Attach ImageDocField: print_designer_preview_img parent=Print Format> value = '/private/files/print_designer-sales_order_pd_v2-preview3f12d3.jpg' unattached_file = None file = <File: unsaved> File "apps/frappe/frappe/model/document.py", line 289, in insert self.run_method("before_insert") self = <File: unsaved> ignore_permissions = True ignore_links = None ignore_if_duplicate = False ignore_mandatory = None set_name = None set_child_names = True File "apps/frappe/frappe/model/document.py", line 974, in run_method out = Document.hook(fn)(self, *args, **kwargs) self = <File: unsaved> method = 'before_insert' args = () kwargs = {} fn = <function Document.run_method.<locals>.fn at 0x75d9041d59e0> File "apps/frappe/frappe/model/document.py", line 1334, in composer return composed(self, method, *args, **kwargs) self = <File: unsaved> args = () kwargs = {} hooks = [] method = 'before_insert' doc_events = {'*': {'on_update': ['frappe.desk.notifications.clear_doctype_notifications', 'frappe.workflow.doctype.workflow_action.workflow_action.process_workflow_actions', 'frappe.core.doctype.file.utils.attach_files_to_document', 'frappe.automation.doctype.assignment_rule.assignment_rule.apply', 'frappe.automation.doctype.assignment_rule.assignment_rule.update_due_date', 'frappe.core.doctype.user_type.user_type.apply_permissions_for_non_standard_user_type'], 'after_rename': ['frappe.desk.notifications.clear_doctype_notifications'], 'on_cancel': ['frappe.desk.notifications.clear_doctype_notifications', 'frappe.workflow.doctype.workflow_action.workflow_action.process_workflow_actions', 'frappe.automation.doctype.assignment_rule.assignment_rule.apply'], 'on_trash': ['frappe.desk.notifications.clear_doctype_notifications', 'frappe.workflow.doctype.workflow_action.workflow_action.process_workflow_actions'], 'on_update_after_submit': ['frappe.workflow.doctype.workflow_action.workflow_action.process_w... composed = <function Document.hook.<locals>.compose.<locals>.runner at 0x75d9041d6160> compose = <function Document.hook.<locals>.compose at 0x75d9041d5940> f = <function Document.run_method.<locals>.fn at 0x75d9041d59e0> File "apps/frappe/frappe/model/document.py", line 1316, in runner add_to_return_value(self, fn(self, *args, **kwargs)) self = <File: unsaved> method = 'before_insert' args = () kwargs = {} add_to_return_value = <function Document.hook.<locals>.add_to_return_value at 0x75d9041d5bc0> fn = <function Document.run_method.<locals>.fn at 0x75d9041d59e0> hooks = () File "apps/frappe/frappe/model/document.py", line 971, in fn return method_object(*args, **kwargs) self = <File: unsaved> args = () kwargs = {} method_object = <bound method File.before_insert of <File: unsaved>> method = 'before_insert' File "apps/frappe/frappe/core/doctype/file/file.py", line 104, in before_insert self.save_file(content=self.get_content()) self = <File: unsaved> File "apps/frappe/frappe/core/doctype/file/file.py", line 539, in get_content with open(file_path, mode="rb") as f: self = <File: unsaved> file_path = './mtech.local/private/files/print_designer-sales_order_pd_v2-preview3f12d3.jpg' builtins.FileNotFoundError: [Errno 2] No such file or directory: './mtech.local/private/files/print_designer-sales_order_pd_v2-preview3f12d3.jpg'

@vintalie
Copy link

vintalie commented Jan 15, 2025

thats is the code snippet:

def attach_files_to_document(doc: "Document", event) -> None:
	"""Runs on on_update hook of all documents.
	Goes through every file linked with the Attach and Attach Image field and attaches
	the file to the document if not already attached. If no file is found, a new file
	is created.
	"""

	attach_fields = doc.meta.get("fields", {"fieldtype": ["in", ["Attach", "Attach Image"]]})

	for df in attach_fields:
		# this method runs in on_update hook of all documents
		# we dont want the update to fail if file cannot be attached for some reason
		value = doc.get(df.fieldname)
		if not (value or "").startswith(("/files", "/private/files")):
			continue

		if frappe.db.exists(
			"File",
			{
				"file_url": value,
				"attached_to_name": doc.name,
				"attached_to_doctype": doc.doctype,
				"attached_to_field": df.fieldname,
			},
		):
			continue

		unattached_file = frappe.db.exists(
			"File",
			{
				"file_url": value,
				"attached_to_name": None,
				"attached_to_doctype": None,
				"attached_to_field": None,
			},
		)

		if unattached_file:
			frappe.db.set_value(
				"File",
				unattached_file,
				field={
					"attached_to_name": doc.name,
					"attached_to_doctype": doc.doctype,
					"attached_to_field": df.fieldname,
					"is_private": cint(value.startswith("/private")),
				},
			)
			continue

		file: File = frappe.get_doc(
			doctype="File",
			file_url=value,
			attached_to_name=doc.name,
			attached_to_doctype=doc.doctype,
			attached_to_field=df.fieldname,
			folder="Home/Attachments",
		)
		try:
			file.insert(ignore_permissions=True)
		except Exception:
			doc.log_error("Error Attaching File")

from = https://github.com/frappe/frappe/blob/develop/frappe/core/doctype/file/utils.py

analyzing this code it seems to me that first it checks if the value received exists, if it is different from an empty string, and does not start with "/files" or "/private/files", then it will check the existence of the file in the db, and if it doesn't exist, it will create a new one. It seems to me that the attacked image is not in the database and the function tries to overwrite it, generating an error.

sorry for the english from the google translator
Can you send me a print of the image folder and the File table in the database?

@MiDOZ
Copy link

MiDOZ commented Jan 16, 2025

Hello, thank you for your feedback, here are the files:

user@erpnext:~/frappe-bench/sites/site.name/private/files$ ls -l
total 16
-rw-r--r-- 1 user user 15820 Jan 13 16:00 500.png

select * from tabFile

query.xlsx

Please note that this is a new setup

@vintalie
Copy link

vintalie commented Jan 16, 2025

The error seems to be simpler than it seems, perhaps Python is unable to access the file's destination url. see that the function first checks if it is a url, after that it uses a function to search for the path (or url) of the file.

How are your files being served? Do you have a system (eg nginx)? Can you somehow access the image via the url? As you said, this is a clean installation so I'm going to disregard that there is any app permissions setting preventing access.

It will be useful to know how you did the entire process and if you have any configuration to deploy.

Image

one thing I also noticed is that @MiDOZ url starts with ./mtech.local and @RaySolo starts with /erpdev.lan, maybe thats a folder name in www, if is possible to remove this subpath, try it
test accessing
localhost/mtech.local/private/files/print_designer-sales_order_pd_v2-preview3f12d3.jpg or
localhost/private/files/print_designer-sales_order_pd_v2-preview3f12d3.jpg (logged)

@MiDOZ
Copy link

MiDOZ commented Jan 16, 2025

It's actually very weird, I have two different sites hosted on two different ports, both in production.
they are system.com and mtech.local.

Image

Image

System.com - Print designer layout and preview with error on MT-Sales-Invoice
Image
Image

mtech.local designer + preview

Image
Image

original design preview error too
Image

Error when clicking PDF download
Image

mtech.local when clicking on PDF download.txt

system.com error.txt

The paths in the db are considering the root folder is the site folder.

@maharshivpatel
Copy link
Collaborator

@MiDOZ as you can see in the error you have incorrect wkhtmltopdf version. please install correct version using instructions shared in error or in FAQ No 1. https://github.com/frappe/print_designer?tab=readme-ov-file#faq

@MiDOZ
Copy link

MiDOZ commented Jan 16, 2025

@MiDOZ as you can see in the error you have incorrect wkhtmltopdf version. please install correct version using instructions shared in error or in FAQ No 1. https://github.com/frappe/print_designer?tab=readme-ov-file#faq

@maharshivpatel I installed the correct version now, but I'm presented with another error:

Traceback (most recent call last): File "apps/frappe/frappe/app.py", line 114, in application response = frappe.api.handle(request) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "apps/frappe/frappe/api/__init__.py", line 49, in handle data = endpoint(**arguments) ^^^^^^^^^^^^^^^^^^^^^ File "apps/frappe/frappe/api/v1.py", line 36, in handle_rpc_call return frappe.handler.handle() ^^^^^^^^^^^^^^^^^^^^^^^ File "apps/frappe/frappe/handler.py", line 50, in handle data = execute_cmd(cmd) ^^^^^^^^^^^^^^^^ File "apps/frappe/frappe/handler.py", line 86, in execute_cmd return frappe.call(method, **frappe.form_dict) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "apps/frappe/frappe/__init__.py", line 1726, in call return fn(*args, **newargs) ^^^^^^^^^^^^^^^^^^^^ File "apps/frappe/frappe/utils/typing_validations.py", line 31, in wrapper return func(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^ File "apps/frappe/frappe/utils/print_format.py", line 236, in download_pdf pdf_file = frappe.get_print( ^^^^^^^^^^^^^^^^^ File "apps/frappe/frappe/__init__.py", line 2142, in get_print return get_pdf(html, options=pdf_options, output=output) if as_pdf else html ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "apps/frappe/frappe/utils/pdf.py", line 90, in get_pdf filedata = pdfkit.from_string(html, options=options or {}, verbose=True) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "env/lib/python3.11/site-packages/pdfkit/api.py", line 75, in from_string return r.to_pdf(output_path) ^^^^^^^^^^^^^^^^^^^^^ File "env/lib/python3.11/site-packages/pdfkit/pdfkit.py", line 201, in to_pdf self.handle_error(exit_code, stderr) File "env/lib/python3.11/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

Image

@RaySolo
Copy link

RaySolo commented Jan 18, 2025

To isolate the problem, I replaced the routine get_pdf() within pdf.py, in which wkhtmltopdf is called, with a routine that works with puppeteer. The problem disappeared. The form previously created with print designer could be displayed.
i fear that many of our problems probably have more to do with wkhtmltopdf than we would like. maybe now is a good time to make the change.

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

No branches or pull requests

5 participants