shaked
shaked

Reputation: 642

firebase function Puppeteer Could not find Chromium GCP

I have been using GCP for a long time with google cloud, and I wanted to run a cloud function that uses Puppeteer, but unfortunately, I am getting the following error.


Unhandled error Error: Could not find Chromium (rev. 1069273). This can occur if either

  1. you did not install before running the script (e.g., npm install) or
  2. your cache path is incorrectly configured (which is: /root/.cache/puppeteer). For (2), check out our guide on configuring Puppeteer at https://pptr.dev/guides/configuration. at ChromeLauncher.resolveExecutablePath (/workspace/node_modules/puppeteer-core/lib/cjs/puppeteer/node/ProductLauncher.js:120:27) at ChromeLauncher.executablePath (/workspace/node_modules/puppeteer-core/lib/cjs/puppeteer/node/ChromeLauncher.js:166:25) at ChromeLauncher.launch (/workspace/node_modules/puppeteer-core/lib/cjs/puppeteer/node/ChromeLauncher.js:70:37) at async /workspace/lib/index.js:122:21 at async /workspace/node_modules/firebase-functions/lib/common/providers/https.js:407:26

My code is


export const test = functions
  .runWith({
    timeoutSeconds: 120,
    memory: "512MB" || "2GB",
  })
  .https.onCall(async (data, context) => {
    const browser = await puppeteer.launch({ args: ["--no-sandbox"] });
    const page = await browser.newPage();
    await page.goto("https://www.google.com/");

    browser.close();
    return { msg: "all good", status: 200 };
  });

I copy from here an example of how to use Puppeteer in the GCP function (worked on my machine), I also tried other functions that don't use Puppeteer, which work fine (so I am sure the problem is with Puppeteer). I also tried to add the flag "--disable-setuid-sandbox" but that didn't work. I am writing the firebase function with Typescript. My package.json has the following settings.

"engines": {
    "node": "16"
  },
  "main": "lib/index.js",
  "dependencies": {
    "firebase-admin": "^10.2.0",
    "firebase-functions": "^3.21.0",
    "puppeteer": "^19.4.0"
  },
  "devDependencies": {
    "@types/puppeteer": "^7.0.4",
    "typescript": "^4.6.4"
  },
  "private": true

My tsconfig.json file has the following setting.

{
  "compilerOptions": {
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "noImplicitReturns": true,
    "noUnusedLocals": true,
    "outDir": "lib",
    "sourceMap": true,
    "strict": true,
    "target": "ES2020",
    "esModuleInterop": true,
    "rootDir": "src",
  },
  "compileOnSave": true,
  "include": [
    "src",
    "node_modules/@types/puppeteer/index.d.ts"
  ]
}

I also have in the lib directory the .puppeteerrc.cjs file according to here.

const {join} = require('path');

/**
 * @type {import("puppeteer").Configuration}
 */
module.exports = {
  // Changes the cache location for Puppeteer.
  cacheDirectory: join(__dirname, '.cache', 'puppeteer'),
};

I tried adding it next to index.js, index.ts,package.json, firebase.json, but that did not change it. I tried deleting and reinstalling node_modules. I tried to follow StackOverflow questions. Deploying firebase function with Puppeteer says chrome can't be found even thoough I have enabled --no-sandbox

Not able to migrate firebase functions to node 10 runtime

puppeteer-in-firebase-functions-failed-to-launch-chrome

Upvotes: 19

Views: 7041

Answers (9)

byiringiro billy
byiringiro billy

Reputation: 71

The most reliable way I’ve addressed this issue across various versions of Puppeteer—given that different versions look for the Chrome cache in different locations—has been to add a postinstall script in package.json. This script is triggered by GCP Cloud Build (or any CI pipeline) after installing the package. In this script, I specify a custom cache directory for Puppeteer to use during installation. Additionally, I include a puppeteer.config.cjs file to ensure the custom cache directory is correctly referenced during runtime.

Here’s a step-by-step breakdown of the solution:

  1. Add a postinstall script to your package.json This will override the default Puppeteer cache directory during installation. For example:

    "postinstall": "PUPPETEER_CACHE_DIR=node_modules/puppeteer/.local-chromium npx puppeteer browsers install chrome"

  2. Create a puppeteer.config.cjs file Define the custom cache directory in this configuration file so that Puppeteer knows where to find the browser files. Example:

    const path = require('path');
    
    module.exports = {
      cacheDirectory: process.env.PUPPETEER_CACHE_DIR || path.join(__dirname, 'node_modules/puppeteer/.local-chromium')
    };
    

For more info checkout this troubleshot page: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md

Upvotes: 0

Jimmy_m
Jimmy_m

Reputation: 1598

To summarize, I did the following and it worked:

Create file .puppeteerrc.cjs in project root with:

const { join } = require("path");

module.exports = { cacheDirectory: join(__dirname, "node_modules", ".puppeteer_cache") };

In package.json scripts section add:

    "postinstall": "puppeteer browsers install chrome",
    "gcp-build": "node node_modules/puppeteer/install.mjs"

In index.js modify the function definition to add memory and timeoutSeconds values:

export const functionNameBlerg = functions.https.onRequest(
  {
    enforceAppCheck: environment.isProd,
    memory: "4GiB",
    timeoutSeconds: 540,
  },
  async (request, response) => {
    await innerFunctionBlerg(request, response);
  }
);

I don't know whether both 'postinstall' and 'gcp-build' items are needed in package.json but it's working this way so....

Upvotes: 0

The only thing that finally work for me was to add this .puppeteerrc.cjs file in my functions folder :

const {join} = require('path');

module.exports = { cacheDirectory: join(__dirname, 'node_modules', '.puppeteer_cache'), };

as explained at the Running Puppeteer on Google Cloud Functions section of this piece of documentation: https://pptr.dev/troubleshooting#running-puppeteer-on-google-cloud-functions

Upvotes: 2

david snyder
david snyder

Reputation: 414

What has worked for me is using Puppeteer ^21.6.0, I add a postinstall script to my package.json to install chrome. Along with puppeteerrc.js file that others have suggested.

"postinstall": "puppeteer browsers install chrome"

Somehow this results in the function having the browser available on every execution. I guess npm install gets called before execution, or something like that. It didn't work when I used a gcp-build script.

Upvotes: 4

Mohammed Abuiriban
Mohammed Abuiriban

Reputation: 510

Add "gcp-build": "node node_modules/puppeteer/install.mjs" to the scripts and make sure that you have a .puppeteerrc.cjs at the root directory which includes the following

const {join} = require('path');
module.exports = {
  cacheDirectory: join(__dirname, '.cache', 'puppeteer')
};

**** Note install.mjs not install.js *****

Upvotes: 3

amit
amit

Reputation: 292

This is the documentation on how to bundle puppeteer. https://pptr.dev/guides/configuration#examples

Create a new file in the root of the application, (usually the functions folder) named ".puppeteerrc.cjs".

Add the following configuration to it:

const {join} = require('path');

/**
 * @type {import("puppeteer").Configuration}
 */
module.exports = {
  // Changes the cache location for Puppeteer.
  cacheDirectory: join(__dirname, '.cache', 'puppeteer'),
};

after adding the file you'll need to reinstall puppeteer.

npm remove puppeteer
npm i puppeteer

Add the new .cache folder to .gitignore.

Add the new .cache folder to firebase.json functions ignore. open firebase.json, find the ignore array under functions, and add ".cache" to it.

Upvotes: 4

stuisme
stuisme

Reputation: 419

I had this issue with puppeteer ^19.8.0 on cloud-functions. The issue was the build layer used when deploying cloud functions contains the chromium binaries already. A simple node_modules/puppeteer/install.js said it already found in the build log. cloud-functions use a different base container image for runtime. The trick was the set the cache directory inside the application source directory. Using puppeteer.config.js file in the root and the sample from the docs:

const { join } = require("path");

/**
 * @type {import("puppeteer").Configuration}
 */
module.exports = {
  // Changes the cache location for Puppeteer.
  cacheDirectory: join(__dirname, ".cache", "puppeteer"),
};

GCP cloud-functions copies the source code directory to the runtime container allowing it to find the cache. Cheers.

Upvotes: 4

Sebastian Viereck
Sebastian Viereck

Reputation: 5887

downgrading puppeteer helped:

npm remove puppeteer
npm install [email protected] --save-dev

Upvotes: 8

Thomas Mahn
Thomas Mahn

Reputation: 59

I faced a similar issue. The simplest fix that I could find was to downgrade to Puppeteer 16.2.0 version. It is a deprecated version of Puppeteer but it should work.

Cheers

Upvotes: 5

Related Questions