Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

executablePath error in puppeteer to launch a lambda function

I have encountred a problem in my sst app where i wanted to launch a puppeteer lambda function

import puppeteer from 'puppeteer-core';
import chromium from '@sparticuz/chromium';

export async function handler() {
  console.log('Launching browser...');
  const browser = await puppeteer.launch({
    args: chromium.args,
    defaultViewport: chromium.defaultViewport,
    executablePath: await chromium.executablePath(),
    headless: chromium.headless,
  });

these are my installed dependencies:

  "dependencies": {
    "@aws-cdk/aws-iam": "^1.204.0",
    "@aws-cdk/aws-s3": "^1.204.0",
    "@aws-sdk/client-s3": "^3.540.0",
    "@sparticuz/chromium": "119",
    "aws-sdk": "^2.1590.0",
    "chrome-aws-lambda": "^10.1.0",
    "puppeteer": "^22.6.1",
    "puppeteer-core": "21.5.0"
  }

But i've got Error: The input directory "/var/task/packages/functions/bin" does not exist. in the deployment.

like image 494
rayn Avatar asked Nov 30 '25 16:11

rayn


1 Answers

I'm facing the same issue with sst. I downloaded the zip from https://github.com/Sparticuz/chromium?tab=readme-ov-file, and added the zip to the layers, attached it to the lambda function. But the puppeteer kept got the error: ERROR Error generating receipt: Error: The input directory "/var/task/app/stacks/bin" does not exist. I checked the source code of the @sparticuz/chromium:

static async executablePath(input) {
        /**
         * If the `chromium` binary already exists in /tmp/chromium, return it.
         */
        if ((0, node_fs_1.existsSync)("/tmp/chromium") === true) {
            return Promise.resolve("/tmp/chromium");
        }
        /**
         * If input is a valid URL, download and extract the file. It will extract to /tmp/chromium-pack
         * and executablePath will be recursively called on that location, which will then extract
         * the brotli files to the correct locations
         */
        if (input && (0, helper_1.isValidUrl)(input)) {
            return this.executablePath(await (0, helper_1.downloadAndExtract)(input));
        }
        /**
         * If input is defined, use that as the location of the brotli files,
         * otherwise, the default location is ../bin.
         * A custom location is needed for workflows that using custom packaging.
         */
        input ??= (0, node_path_1.join)(__dirname, "..", "bin");
        /**
         * If the input directory doesn't exist, throw an error.
         */
        if (!(0, node_fs_1.existsSync)(input)) {
            throw new Error(`The input directory "${input}" does not exist.`);
        }
        // Extract the required files
        const promises = [
            lambdafs_1.default.inflate(`${input}/chromium.br`),
            lambdafs_1.default.inflate(`${input}/fonts.tar.br`),
        ];
        if (this.graphics) {
            // Only inflate graphics stack if needed
            promises.push(lambdafs_1.default.inflate(`${input}/swiftshader.tar.br`));
        }
        if ((0, helper_1.isRunningInAwsLambda)()) {
            // If running in AWS Lambda, extract more required files
            promises.push(lambdafs_1.default.inflate(`${input}/al2.tar.br`));
        }
        if ((0, helper_1.isRunningInAwsLambdaNode20)()) {
            promises.push(lambdafs_1.default.inflate(`${input}/al2023.tar.br`));
        }
        // Await all extractions
        const result = await Promise.all(promises);
        // Returns the first result of the promise, which is the location of the `chromium` binary
        return result.shift();
    }

Then I tried to print all folders in the /tmp and the /opt, only node-moudles folders but no chromium-related layers were found. I finally gave up on this solution due to the deadline approaching.

like image 175
Dre Avatar answered Dec 05 '25 00:12

Dre



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!