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

[BUG] TimeoutError: Timed out after waiting 30000ms #291

Open
giri0996 opened this issue Aug 21, 2024 · 8 comments
Open

[BUG] TimeoutError: Timed out after waiting 30000ms #291

giri0996 opened this issue Aug 21, 2024 · 8 comments
Labels
bug Something isn't working

Comments

@giri0996
Copy link

giri0996 commented Aug 21, 2024

Environment

  • chromium Version: 126.0.0
  • puppeteer-core Version: 22.12.1
  • Node.js Version: 18.x | 20.x
  • Lambda: nodejs18.x | nodejs20.x

Expected Behavior

Generate the pdf and upload to an s3 bucket

Current Behavior

The same code base was working before in nodejs 14.x lambda runtime having chrome-aws-lambda 6.0.0 puppeteer/puppeteer-core 6.0.0.

In Node18.x/20.x lambda runtimegetting a TimeoutError during pdf generation.

Failed to print PDF on time.

TimeoutError: Timed out after waiting 30000ms
    at /var/task/node_modules/puppeteer-core/lib/cjs/puppeteer/common/util.js:289:19
    at /var/task/node_modules/puppeteer-core/lib/cjs/third_party/rxjs/rxjs.js:3986:35
    at OperatorSubscriber2._this._next (/var/task/node_modules/puppeteer-core/lib/cjs/third_party/rxjs/rxjs.js:1055:13)
    at Subscriber2.next (/var/task/node_modules/puppeteer-core/lib/cjs/third_party/rxjs/rxjs.js:678:16)
    at AsyncAction2.<anonymous> (/var/task/node_modules/puppeteer-core/lib/cjs/third_party/rxjs/rxjs.js:4863:24)
    at AsyncAction2._execute (/var/task/node_modules/puppeteer-core/lib/cjs/third_party/rxjs/rxjs.js:1974:16)
    at AsyncAction2.execute (/var/task/node_modules/puppeteer-core/lib/cjs/third_party/rxjs/rxjs.js:1963:26)
    at AsyncScheduler2.flush (/var/task/node_modules/puppeteer-core/lib/cjs/third_party/rxjs/rxjs.js:2235:30)
    at listOnTimeout (node:internal/timers:569:17)
    at process.processTimers (node:internal/timers:512:7) {
  [cause]: undefined
}

Steps to Reproduce

const url = require('url');

const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');

const puppeteer = require('puppeteer-core');

const chromium = require('@sparticuz/chromium');


const timeoutPromise = async function(promise, ms = 60000) {
    let id;

    // Create a promise that rejects in <ms> milliseconds
    let timeout = new Promise((resolve, reject) => {
        id = setTimeout(() => {
            reject('Timed out in ' + ms + 'ms.')
        }, ms)
    });

    return Promise.race([promise, timeout]).then((result) => {
        clearTimeout(id);

        return result;
    });
};

exports.generatePdfHandler = async function(event, context) {
    /*
    This is the entry point for the Lambda function.

    */
    const s3Client = new S3Client();

    const browser = await puppeteer.launch({
        executablePath: await chromium.executablePath(),
        headless: chromium.headless,
        args: [
            '--no-sandbox',
            '--single-process',
            '--homedir=/tmp',
            '--data-path=/tmp/data-path',
            '--disk-cache-dir=/tmp/cache-dir'
        ]
    });
    const page = await browser.newPage();
    // Set viewport size so that CSS won't break in print mode. This was tested
    // to be working, anything below or above this standard resolution did not
    // work.
    await page.setViewport({width: 1024, height: 768});
    // Disable navigation timeout so that we allow more than 30 seconds to load
    // a report.
    await page.setDefaultNavigationTimeout(0);

    console.log(`Fetching report from ${event.reportUrl}`);
    try {
        await page.goto(event.reportUrl, {waitUntil: 'networkidle0'});
    } catch (err) {
        console.log('Failed to load report.');
        console.log(err);
        await browser.close();
        return;
    }
    console.log('Report page fully loaded.');

    // Verify that an actual report was rendered, making sure we have charts
    // in the DOM.
    let hasReports = false;
    try {
        hasReports = (await page.$eval('ca-reports', el => el.childElementCount)) > 0;
    } catch (err) {
        console.log('Could not find parent ca-reports element');
    }
    if (!hasReports) {
        console.log('Could not find any charts in the rendered report.');
        let screenshot = await page.screenshot({fullPage: true});
        let screenshotKeyName = event.pdfKeyName.replace('.pdf', '-error.png');
        const params = {
            Bucket: event.bucketName,
            ACL: 'private',
            Key: screenshotKeyName,
            Body: screenshot,
            ContentType: 'image/png',
            ServerSideEncryption: 'aws:kms',
            SSEKMSKeyId: process.env.PDF_KMS_KEY_ID
        };
        const command = new PutObjectCommand(params);
        await s3Client.send(command);
        console.log(`Saving Error screenshot to s3://${event.bucketName}/${screenshotKeyName}`);
        await browser.close();
        return;
    }

    const printToPdf = async function () {
        return page.pdf({printBackground: true, landscape: false});
    };

    await timeoutPromise(printToPdf(), (context.getRemainingTimeInMillis() || 2000) - 2000).then(async (pdf) => {
        try {
            const params = {
                Bucket: event.bucketName,
                ACL: 'private',
                Key: event.pdfKeyName,
                Body: pdf,
                ContentType: 'application/pdf',
                ContentDisposition: 'attachment',
                ServerSideEncryption: 'aws:kms',
                SSEKMSKeyId: process.env.PDF_KMS_KEY_ID
            };
            const command = new PutObjectCommand(params);
            await s3Client.send(command);
            console.log(`PDF successfully saved as s3://${event.bucketName}/${event.pdfKeyName}`);

            await browser.close();
            return;
        } catch (err) {
            console.log('Failed to upload PDF.');
            console.log(err);
            await browser.close();
            return;
        }
        await browser.close();
        return;
    }).catch(async (err) => {
        console.log('Failed to print PDF on time.');
        console.log(err);
        await browser.close();
        return;
    });
};

Lambda Memory - 4096 MB, Ephemeral storage - 512 MB, Timeout - 6 MIN

Can some one help me to figure out what is wrong here?

@giri0996 giri0996 added the bug Something isn't working label Aug 21, 2024
@Madebyspeedster
Copy link

Hi, does it happens on specific pages?

@giri0996
Copy link
Author

I have mostly seen this behaviour on pdf's with large file sizes around 50 MB, page count approx 750

@Madebyspeedster
Copy link

Madebyspeedster commented Sep 24, 2024

oh, it's kinda heavy, I've asked, I'm getting same error, but in my case it's pretrty simple page.
Page has style tag with CSS inside, weird part is - when I use

 @media print {
        .non-pdf-link {
          display: none !important;
        }
        .pdf-link {
          display: flex !important;
        }
        .main-content {
          zoom: 145%;
        }
      }

page.pdf(...options) throw Error waiting timeout, even if I increase it still occurs.
and in case I've removed media print styles, it works)

@Madebyspeedster
Copy link

I've updated a lib and issue has gone =)

@giri0996
Copy link
Author

giri0996 commented Oct 7, 2024

Could you tell me what was updated here for the issue to be gone?

@Madebyspeedster
Copy link

Hi, I have just upgraded the library to the latest version, following the guidelines outlined in the documentation.

image

@giri0996
Copy link
Author

I tried with the latest library puppeteer-core == 23.6.1 and chromium Version: 130.0.0, but still receiving the same timeout error

TimeoutError: Timed out after waiting 30000ms at /var/task/node_modules/puppeteer-core/lib/cjs/puppeteer/common/util.js:258:19 at /var/task/node_modules/puppeteer-core/lib/cjs/third_party/rxjs/rxjs.js:3986:35 at OperatorSubscriber2._this._next (/var/task/node_modules/puppeteer-core/lib/cjs/third_party/rxjs/rxjs.js:1055:13) at Subscriber2.next (/var/task/node_modules/puppeteer-core/lib/cjs/third_party/rxjs/rxjs.js:678:16) at AsyncAction2.<anonymous> (/var/task/node_modules/puppeteer-core/lib/cjs/third_party/rxjs/rxjs.js:4863:24) at AsyncAction2._execute (/var/task/node_modules/puppeteer-core/lib/cjs/third_party/rxjs/rxjs.js:1974:16) at AsyncAction2.execute (/var/task/node_modules/puppeteer-core/lib/cjs/third_party/rxjs/rxjs.js:1963:26) at AsyncScheduler2.flush (/var/task/node_modules/puppeteer-core/lib/cjs/third_party/rxjs/rxjs.js:2235:30) at listOnTimeout (node:internal/timers:581:17) at process.processTimers (node:internal/timers:519:7) { [cause]: undefined }

@ajmal-ahmed
Copy link

I've faced this issue and got this working with the following versions

"@sparticuz/chromium": "^130.0.0",
"puppeteer-chromium-resolver": "^23.0.0",
"puppeteer-core": "^23.7.1"

Here is my code


"use strict";
const puppeteer = require("puppeteer-core");
const PCR = require("puppeteer-chromium-resolver");

exports.generatePdfFromUrl = async (urlToPrint) => {
    try {
        const stats = await PCR();
        const browser = await puppeteer.launch({
            headless: true,
            args: ['--no-sandbox'],
            executablePath: stats.executablePath,
            defaultViewport: { width: 1920, height: 945, deviceScaleFactor: 4 },
        });

        const options = {
            format: 'A4',
            headerTemplate: '',
            footerTemplate: '',
            displayHeaderFooter: false,
            margin: {
                top: '0px',
                bottom: '0px',
            },
            printBackground: true,
        };

        const page = await browser.newPage();
        await page.setDefaultNavigationTimeout(60000); // Set timeout to 60 seconds

        await page.goto(urlToPrint, {
            waitUntil: 'networkidle0',
        });

        // Wait for 5 seconds to ensure all content is loaded
        await new Promise(resolve => setTimeout(resolve, 5000));
        const buffer = await page.pdf(options);

        await page.close();
        await browser.close();

        return buffer;
    } catch (error) {
        console.error(error);
        throw error;
    }
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants