marcbachmann / node-html-pdf

This repo isn't maintained anymore as phantomjs got dreprecated a long time ago. Please migrate to headless chrome/puppeteer.
MIT License
3.55k stars 545 forks source link

occasional SyntaxError: Unexpected end of input, when creating pdf stream from string #108

Open eladkarakuli opened 8 years ago

eladkarakuli commented 8 years ago

Hi, I'm getting strange errors, occasionally, mostly on first tries (I'm doing retries of if it fails), my code:

return () => new Promise((res, rej) => {
        let html = `${htmlStart}${htmlBody}${htmlEnd}`;

        pdf.create(html).toStream(function (err, stream) {
            if (err) {
                rej(new Error("Fail converting html to pdf stream. html:" + htmlBody + " Error:" + err ));
            }

            res(stream);
        });
    });

html='<!DOCTYPE HTML><html><body>A new-</body></html>'
throws SyntaxError: Unexpected end of input.

I'm returning a function that when called returns the promise (sometimes I won't need the function to be called)

using: html-pdf: 1.5.0, phantomjs 1.9.8

medikoo commented 8 years ago

Having exactly same issue on Ubuntu, it looks it's related to this line -> https://github.com/marcbachmann/node-html-pdf/blob/master/lib/pdf.js#L128 When looking one line up, it's clear that data may turn as undefined (void 0), and making JSON.parse(undefined) throws SyntaxError: Unexpected end of input

marcbachmann commented 8 years ago

@medikoo so what do you think? Why isn't there an exit code or error if there's no content? That shouldn't happen.

medikoo commented 8 years ago

@marcbachmann I'm not that familiar with internals of this module.

Still I've "fixed" it for my case by replacing:

data = JSON.parse(data);

with

data = data ? JSON.parse(data) : {};

Still it means that for some cases what goes into callback (which is few lines below) is in form of { filename: ... } and in some other (those which raised that error) it is {}. I can't say if it's ok or not.

medikoo commented 8 years ago

@marcbachmann small correction, Buffer.concat(stdout).toString() resolves either to empty string, or plain whitespace. thendata when assigned with buf.trim() resolves to '', and its JSON.parse('') that throws SyntaxError: Unexpected end of input.

Anyway I still refer to version v1.5 (I have not yet tried v2.0)

marcbachmann commented 8 years ago

Yes, doesn't matter. It's the same problem, the input is invalid. Thanks for investigating. On the render callback of the page inside phantom, the script doesn't check for an error code. Maybe the page rendering fails somehow.

medikoo commented 8 years ago

@marcbachmann good point, I take a look into that, and get back if I have some more info

medikoo commented 8 years ago

@marcbachmann anyway what's in a code, is clearly a bug. There should be no JSON.parse called when we know that data is empty string. If it's indeed a result of some error, throwing some more meaningful message (instead of doing JSON.parse that can't work) would help.

marcbachmann commented 8 years ago

Thanks. It's that one. https://github.com/marcbachmann/node-html-pdf/blob/master/lib/scripts/pdf_a4_portrait.js#L75 Or that: https://github.com/marcbachmann/node-html-pdf/blob/master/lib/scripts/pdf_a4_portrait.js#L55

Maybe also page.render fails. A try catch might help.

Tollman commented 7 years ago

Hi! This error occurs because the event 'exit' using in the library. This event happens earlier than: child.stdout.on('data'), so in child.on('exit') variable stdout will be empty array and JSON.parse will fall.

I changed the use of the event "exit" to "close" and this error is not repeated.

flaviodelbianco commented 7 years ago

I have the same issue, any fix for this?

micahbule commented 6 years ago

I think the issue still persists because of the following line of code: https://github.com/marcbachmann/node-html-pdf/blob/master/lib/scripts/pdf_a4_portrait.js#L70

It's totally logical to call exit after successfully rendering the PDF. It also makes sense that a successful exit doesn't have any data to return to the parent process, especially if the output filename was already written to the stdout. This is where the problem lies because the parent process considers any response without data from the child process as an error (https://github.com/marcbachmann/node-html-pdf/blob/master/lib/pdf.js#L120), regardless if there were actually any errors thrown from the child process or whatever the value of the exit code is.

Here is a pull request from my fork: https://github.com/marcbachmann/node-html-pdf/pull/418

I included comments there as to why I wrote it like that. Kindly take a look and lemme know if I missed anything.

Thanks.