PDF Generation failed/Invoice Locking error

I am trying to set up v5 but when creating an invoice and generating a PDF this error shows up Error
Failed to load PDF document. Also when trying to edit invoice draft I get an error that the invoice cannot be edited even though the setting is on Lock When Sent

Version 5.1.43

Hi,

Have you seen the info here:

https://invoiceninja.github.io/docs/self-host-troubleshooting/#pdf-conversion-issues

cc @david for the lock when sent issue.

I tried installing snappdf but something went wrong and now I get Error 500:

Are there any details about the error in the logs?

1 Like

There doesn’t seem to me anything showing up in the logs, also when I access the url in the access logs i get a 500 | server Error screen, It might also be that I don’t fully understand the process of installing snappdf and something went wrong on that end, but I do not know how to troubleshoot that. Do I just run composer require beganovich/snappdf in the invoice ninja dir?

Have you checked both the web server error logs and the app logs in storage/logs/

yes I have checked both laravel.log and invoiceninja.error/access and neither of them have anything pertaining to the pdf error

this is the get request from nginx access logs
10.10.1.153 - - [13/Apr/2021:10:29:45 -0400] “GET /client/invoice/sGJ5ckZMN1j45KetY7nK8vggNPr2MpLhctqNEBYyfCS885pwXSVodQGktLHk9M9C/download_pdf HTTP/2.0” 500 1558 “https://invoicet.kt.loc/” “Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36” and laravel.log is full of html

Nothing is in the server error logs

@david do you have any ideas?

This is the html from the pdf

[2021-04-13 18:20:06] production.INFO: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><head><style id="style">
    :root {
        --primary-color: #142cb5;
        --secondary-color: #7081e0;
    }

    body {
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
        font-family: Arial, Helvetica, sans-serif;
        font-size: "7px";
        zoom: 80%;
    }

    @page {
        margin: 6.35mm;
        size: A4 portrait;
    }

    p {
        margin: 0;
        padding: 0;
    }

    .header-wrapper {
        display: grid;
        grid-template-columns: 1fr 1fr 1fr;
    }

    .header-wrapper .company-logo {
        height: 5rem;
    }

    .header-wrapper #company-address {
        display: flex;
        flex-direction: column;
    }

    .header-wrapper #entity-details {
        margin-top: 1.5rem;
        text-align: left;
        width: 100%;
    }

    .header-wrapper #entity-details > tr,
    .header-wrapper #entity-details th {
        font-weight: normal;
        padding-left: 0.9rem;
        padding-top: 0.3rem;
        padding-bottom: 0.3rem;
    }

    .header-wrapper
    #entity-details
    [data-element='entity-balance-due-label'],
    .header-wrapper
    #entity-details
    [data-element='entity-balance-due'] {
        background-color: #e6e6e6;
    }

    #client-details {
        display: flex;
        flex-direction: column;
    }

    #product-table,
    #delivery-note-table,
    #task-table {
        min-width: 100%;
        table-layout: fixed;
        overflow-wrap: break-word;
        margin-top: 3rem;
        /* margin-bottom: 200px; */
    }

    .task-time-details {
        display: block;
        margin-top: 5px;
        color: grey;
    }

    #product-table > thead,
    #delivery-note-table > thead,
    #task-table > thead {
        text-align: left;
    }

    #product-table > thead > tr > th,
    #delivery-note-table > thead > tr > th,
    #task-table > thead > tr > th {
        padding: 1rem;
        background-color: #e6e6e6;
    }

    #product-table > thead > tr > th:last-child,
    #delivery-note-table > thead > tr > th:last-child,
    #task-table > thead > tr > th:last-child {
        text-align: right;
    }

    #product-table > tbody > tr > td,
    #delivery-note-table > tbody > tr > td,
    #task-table > tbody > tr > td {
        border-bottom: 1px solid #e6e6e6;
        padding: 1rem;
    }

    #product-table > tbody > tr > td:last-child,
    #delivery-note-table > tbody > tr > td:last-child,
    #task-table > tbody > tr > td:last-child {
        text-align: right;
    }

    #table-totals {
        page-break-inside: avoid;
    }

    #table-totals {
        display: grid;
        grid-template-columns: 2fr 1fr;
        padding-top: .5rem;
        padding-left: 1rem;
        gap: 80px;
    }

    #table-totals .totals-table-right-side>* {
        display: grid;
        grid-template-columns: 1fr 1fr;
    }

    #table-totals>.totals-table-right-side>*> :nth-child(1) {
        text-align: left;
    }

    #table-totals>.totals-table-right-side>*> :nth-child(2) {
        text-align: right;
    }

    #table-totals
    > *
    [data-element='total-table-balance-due-label'],
    #table-totals
    > *
    [data-element='total-table-balance-due'] {
        font-weight: bold;
    }

    #table-totals > * > :last-child {
        text-align: right;
        padding-right: 1rem;
    }
</style>
</head><body><div id="header"></div>

<div id="body">
    <div class="header-wrapper">
        <div id="company-details"><p data-ref="company_details-company.name">**********</p><p data-ref="company_details-company.website">****************</p><p data-ref="company_details-company.email">************</p><p data-ref="company_details-company.phone">**********</p></div>
        <div id="company-address"><p data-ref="company_address-company.address1">***************</p><p data-ref="company_address-company.city_state_postal">***********, ***** ******</p><p data-ref="company_address-company.country">******* ******</p></div>

        <div>
            <img class="company-logo" src="https://invoicet.kt.loc/storage/2aFJosTJjiRb54D6aLQIsLKFes0NQ2bDVJ5hfLvKacLPe3uOW7HfRaanfVbIuaAi/ZxAtjTRRXbUAFit8JL3Kas8s5lWkZOjs80QpzoXa.png" alt="******** logo">

            <table id="entity-details" cellspacing="0"><tr><th data-ref="entity_details-invoice.number_label">Invoice Number</th><th data-ref="entity_details-invoice.number">INV-2020-0001</th></tr><tr hidden="1"><th data-ref="entity_details-invoice.po_number_label">PO Number</th><th data-ref="entity_details-invoice.po_number">&nbsp;</th></tr><tr><th data-ref="entity_details-invoice.date_label">Invoice Date</th><th data-ref="entity_details-invoice.date">01/23/2020</th></tr><tr><th data-ref="entity_details-invoice.due_date_label">Due Date</th><th data-ref="entity_details-invoice.due_date">02/02/2020</th></tr><tr><th data-ref="entity_details-invoice.total_label">Invoice Total</th><th data-ref="entity_details-invoice.total">$***.00</th></tr><tr><th data-ref="entity_details-invoice.balance_due_label">Balance Due</th><th data-ref="entity_details-invoice.balance_due">$0.00</th></tr></table>
        </div>
    </div>

    <div id="client-details"><p data-ref="client_details-client.name">************</p><p data-ref="client_details-client.number">0001</p><p data-ref="client_details-client.address1">***********</p><p data-ref="client_details-client.city_state_postal">********** *****, ** *******</p><p data-ref="client_details-client.country">**************</p><p data-ref="client_details-contact.email">******************</p></div>

    <table id="product-table" cellspacing="0"><thead><th data-ref="product_table-product.item-th">Item</th><th data-ref="product_table-product.description-th">Description</th><th data-ref="product_table-product.unit_cost-th">Unit Cost</th><th data-ref="product_table-product.quantity-th">Quantity</th><th data-ref="product_table-product.discount-th">Discount</th><th data-ref="product_table-product.line_total-th">Line Total</th></thead><tbody><tr><td data-ref="product_table-product.item-td">****</td><td data-ref="product_table-product.description-td">*********************************</td><td style="white-space: nowrap;" data-ref="product_table-product.unit_cost-td">$**.00</td><td data-ref="product_table-product.quantity-td">*.00</td><td data-ref="product_table-product.discount-td"></td><td data-ref="product_table-product.line_total-td">$***.00</td></tr><tr><td data-ref="product_table-product.item-td">******</td><td data-ref="product_table-product.description-td"></td><td style="white-space: nowrap;" data-ref="product_table-product.unit_cost-td">$***.00</td><td data-ref="product_table-product.quantity-td">***.00</td><td data-ref="product_table-product.discount-td"></td><td data-ref="product_table-product.line_total-td">$**.00</td></tr></tbody></table>

    <table id="task-table" cellspacing="0"></table>

    <div id="table-totals" cellspacing="0"><div style="display: flex; flex-direction: column;"><p data-ref="total_table-public_notes" style="text-align: left;"></p><p style="text-align: left; display: flex; flex-direction: column;"><span hidden="1" data-ref="total_table-terms-label" style="font-weight: bold; text-align: left; margin-top: 1rem;">Invoice Terms: </span><span data-ref="total_table-terms" style="text-align: left;"></span><span data-ref="total_table-footer" style="text-align: left; margin-top: 1rem;"></span></p><img style="max-width: 50%; height: auto;" src=""><div style="margin-top: 1.5rem; display: flex; align-items: flex-start;"><img src="https://raw.githubusercontent.com/invoiceninja/invoiceninja/v5-develop/public/images/new_logo.png" style="height: 2.5rem;" id="invoiceninja-whitelabel-logo"></div></div><div class="totals-table-right-side"><div><span data-ref="totals_table-subtotal-label">Subtotal</span><span data-ref="totals_table-subtotal">$***.00</span></div><div><span hidden="1" data-ref="totals_table-custom_surcharge1-label"></span><span hidden="1" data-ref="totals_table-custom_surcharge1">$**.00</span></div><div><span hidden="1" data-ref="totals_table-custom_surcharge2-label"></span><span hidden="1" data-ref="totals_table-custom_surcharge2">$0.00</span></div><div><span hidden="1" data-ref="totals_table-custom_surcharge3-label"></span><span hidden="1" data-ref="totals_table-custom_surcharge3">$0.00</span></div><div><span hidden="1" data-ref="totals_table-custom_surcharge4-label"></span><span hidden="1" data-ref="totals_table-custom_surcharge4">$**.00</span></div><div><span data-ref="totals_table-paid_to_date-label">Paid to Date</span><span data-ref="totals_table-paid_to_date">$**.00</span></div><div><span data-ref="totals_table-total-label">Total</span><span data-ref="totals_table-total">$***.00</span></div><div><span></span><span></span></div></div></div>

    <table id="delivery-note-table" cellspacing="0"></table>
</div>

<div id="footer"><div><script>document.querySelectorAll("tbody > tr > td").forEach(t=>{if(""!==t.innerText){let e=t.getAttribute("data-ref").slice(0,-3);document.querySelector(`th[data-ref="${e}-th"]`).removeAttribute("hidden")}}),document.querySelectorAll("tbody > tr > td").forEach(t=>{let e=t.getAttribute("data-ref").slice(0,-3);(e=document.querySelector(`th[data-ref="${e}-th"]`)).hasAttribute("hidden")&&""==t.innerText&&t.setAttribute("hidden","true")});</script></div></div>
</body></html>`Preformatted text`

@david

also @hillel quick question what versions of php does v5 currenly support

so the issue will most likely be with Phantom JS not returning correct PDF, have you registered for a Phantom JS API key and then entered that into the .env file?

i disabled Phantom JS and installed snappdf and it still isn’t working
and even with a Phantom JS API key the PDF just hangs without generating the only difference is there isn’t an error

Does the web user own the entire directory recursively? It sounds like a permissions issue with the webserver unable to write.

i made sure to change permissions when I launched the server, if i don’t change the permissions and try to access the server it tells me the server cannot handle the request.

@kwassef

I’ve tagged a new release 5.1.44, in this version I have much more logging and better error messaging. I would suggest upgrading to this version as it will give you more information.

how should i go about doing that?

@david I have it now and PDF’s are still not working on either version

this is the error i get now

500: 

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Server Error</title>

        <!-- Fonts -->
        <link rel="dns-prefetch" href="//fonts.gstatic.com">
        <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet">

        <!-- Styles -->
        <style>
            html, body {
                background-color: #fff;
                color: #636b6f;
                font-family: 'Nunito', sans-serif;
                font-weight: 100;
                height: 100vh;
                margin: 0;
            }

            .full-height {
                height: 100vh;
            }

            .flex-center {
                align-items: center;
                display: flex;
                justify-content: center;
            }

            .position-ref {
                position: relative;
            }

            .code {
                border-right: 2px solid;
                font-size: 26px;
                padding: 0 15px 0 15px;
                text-align: center;
            }

            .message {
                font-size: 18px;
                text-align: center;
            }
        </style>
    </head>
    <body>
        <div class="flex-center position-ref full-height">
            <div class="code">
                500            </div>

            <div class="message" style="padding: 10px;">
                Server Error            </div>
        </div>
    </body>
</html>

@david @hillel are there any other steps i should attempt to fix this?

@david @hillel I got the pdf generation working I had to add these flags to the .env
SNAPPDF_CHROMIUM_PATH=/snap/bin/chromium(i struggled to find the bin for chromium but it turns out in Ubuntu 20.04 composer installs it using snap, so it ends up in /snap/bin)
SNAPPDF_SKIP_DOWNLOAD=true
NINJA_HOSTED_PDF=true

Once I added those lines the PDF’s would generate but the logo would not and this would show in it’s place.
2021-04-18 21_18_34-Invoice Ninja

I can access the url by pasting the location in my url bar and it shows up in my logs.

[2021-04-18 20:51:04] production.INFO: the path http://invoicet.kt.loc/storage/2aFJosTJjiRb54D6aLQIsLKFes0NQ2bDVJ5hfLvKacLPe3uOW7HfRaanfVbIuaAi/ZAtmJ0e3WVFwLrxZlfX0tQ70JFgE2SCbWNGhCkwM.png
[2021-04-18 22:30:41] production.ERROR: The file "/var/www/html/ninja/public/storage/2aFJosTJjiRb54D6aLQIsLKFes0NQ2bDVJ5hfLvKacLPe3uOW7HfRaanfVbIuaAi/uB46xNk5KUTUnitIVjdTFuuCiwpQqlTNM766EN96/invoices/INV-2020-0001.pdf" does not exist {"exception":"[object] (Symfony\\Component\\HttpFoundation\\File\\Exception\\FileNotFoundException(code: 0): The file \"/var/www/html/ninja/public/storage/2aFJosTJjiRb54D6aLQIsLKFes0NQ2bDVJ5hfLvKacLPe3uOW7HfRaanfVbIuaAi/uB46xNk5KUTUnitIVjdTFuuCiwpQqlTNM766EN96/invoices/INV-2020-0001.pdf\" does not exist at /var/www/html/ninja/vendor/symfony/http-foundation/File/File.php:36)

Also I am still having the issue where I cannot edit any drafted invoices when it is set to Lock When Sent.

@kwassef

is your system publicly accessible? the image would need to be resolvable.