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] Unable to Execute Binary File in Local Development #42

Closed
PickertJoe opened this issue Jan 18, 2023 · 10 comments · Fixed by #76
Closed

[BUG] Unable to Execute Binary File in Local Development #42

PickertJoe opened this issue Jan 18, 2023 · 10 comments · Fixed by #76
Labels
bug Something isn't working

Comments

@PickertJoe
Copy link

PickertJoe commented Jan 18, 2023

Environment

  • chromium Version: 109
  • puppeteer / puppeteer-core Version: 19.5.2
  • Node.js Version: 16
  • Lambda / GCF Runtime: nodejs 16.x
  • MacOS 11.7.2
  • x64 Intel processor and running Lambda with x64 architecture

Expected Behavior

The chromium binary should execute

Current Behavior

{
    "errorMessage": "Failed to launch the browser process!\n/tmp/chromium: /tmp/chromium: cannot execute binary file\n\n\nTROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md\n",
    "errorType": "Error",
    "stackTrace": [
        "Error: Failed to launch the browser process!",
        "/tmp/chromium: /tmp/chromium: cannot execute binary file",
        "",
        "",
        "TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md",
        "",
        "    at onClose (/path-hidden/node_modules/puppeteer-core/lib/cjs/puppeteer/node/BrowserRunner.js:299:20)",
        "    at Interface.<anonymous> (/path-hiddden/node_modules/puppeteer-core/lib/cjs/puppeteer/node/BrowserRunner.js:287:24)",
        "    at Interface.emit (node:events:525:35)",
        "    at Interface.emit (node:domain:489:12)",
        "    at Interface.close (node:readline:590:8)",
        "    at Socket.onend (node:readline:280:10)",
        "    at Socket.emit (node:events:525:35)",
        "    at Socket.emit (node:domain:489:12)",
        "    at endReadableNT (node:internal/streams/readable:1358:12)",
        "    at processTicksAndRejections (node:internal/process/task_queues:83:21)"
    ]
}

Steps to Reproduce

  1. Follow installation steps in documentation (installing @Sparticuz/chromium as a dev dependency)
  2. export IS_LOCAL=true
  3. Try running lambda function with serverless offline

Lambda function code example:

import 'source-map-support/register';

import type { ValidatedEventAPIGatewayProxyEvent } from '@/utils/apiGateway';
import { middyfy } from '@/middleware';

import schema from './schema';

const chromium = require('@sparticuz/chromium');
const puppeteer = require('puppeteer-core');

const capture: ValidatedEventAPIGatewayProxyEvent<typeof schema> = async (
  event,
) => {
  const { queryStringParameters } = event;
  if (
    !queryStringParameters ||
    !queryStringParameters.url ||
    !queryStringParameters.screen
  ) {
    return { statusCode: 403 };
  }

  const { url } = queryStringParameters;
  console.log(queryStringParameters);
  const [width, height] = queryStringParameters.screen.split(',');

  if (!width || !height) {
    return { statusCode: 403 };
  }

  console.log('About to launch the browser...');
  const execPath = await chromium.executablePath();
  console.log(execPath);
  console.log(process.version);
  console.log(process.env.IS_LOCAL);
  const browser = await puppeteer.launch({
    args: chromium.args,
    defaultViewport: chromium.defaultViewport,
    executablePath: await chromium.executablePath(),
    headless: chromium.headless,
    ignoreHTTPSErrors: true,
  });
  const browser = await puppeteer.launch({
    headless: true,
  });
  console.log('I launched the browser!!');

  const page = await browser.newPage();
  await page.setViewport({
    width: Number(width),
    height: Number(height),
  });

  await page.goto('https://example.com');
  console.log(`Page title ${await page.title()}`);
  const screenshot = await page.screenshot({
    path: 'screenshot.png',
    encoding: 'base64',
  });

  await browser.close();

  return {
    statusCode: 200,
    body: `<img src=”data:image/png;base64,${screenshot}”>`,
    headers: { 'Content-Type': 'text/html' },
  };
};

export const main = middyfy(capture);

The console logs confirm that my lambda is running is node 16 and that the chromium.exectubalePath() is pointing to /tmp/chromium.

The function blows up when I try to launch the browser:
const browser = await puppeteer.launch({

When I open /tmp/chromium and attempt to execute the file, I also get
zsh: exec format error: ./chromium. This leads me to believe there may be an issue with the chromium binary file

Possible Solution

@PickertJoe PickertJoe added the bug Something isn't working label Jan 18, 2023
@PickertJoe
Copy link
Author

I believe this is the same issue raised in #27, but the identified root cause there isn't applicable since I'm already using x64. Any help would be greatly appreciated!

@kaykhan
Copy link

kaykhan commented Jan 22, 2023

Having the same issue, did you manage to find any workaround?

@PickertJoe
Copy link
Author

@kaykhan I was not, unfortunately 😞 I ended up switching over to playwright-aws-lambda and have had much better luck! It worked right out of the box

@Sparticuz
Copy link
Owner

Does sls offline run a docker container similar to how aws sam does their testing? If so, you might need to make the binaries available to the container, whether that's making them production dependencies, or layers, etc..

You can also try the @sparticuz/chromium-min package and provide a location for the files.

If you don't need a newer version of chromium, playwright-aws-lamda looks extremely similar to chrome-aws-lambda. The main difference being that chromium is over two years old!

@kaykhan
Copy link

kaykhan commented Jan 24, 2023

Just to clarify but this problem does not only just exists with sls offline. it also exists with sls invoke local -f <function_name>

@Sparticuz
Copy link
Owner

If you specify the package as a production dependency does it work?

@PickertJoe
Copy link
Author

@Sparticuz @kaykhan For further clarification to my posts above, playwright-aws-lambda worked fine locally using serverless offline but did not work when actually deployed. Probably to your point @Sparticuz that the binaries included in that package are super old.

Using this package as a production dependency, everything works perfectly in deployed environments! But I'm still seeing the same error described above in which my local environment seems unable to run the inflated executable file. Would you mind sharing where you're sourcing these binaries @Sparticuz? I don't know if there are any OS-related gotchas here, but my hunch is that there might be. I'm also going to try running my project on my Linux machine this weekend to see if this local dev issue is still present there

@kaykhan
Copy link

kaykhan commented Jan 25, 2023

If you specify the package as a production dependency does it work?

Ive been installing via npm install <package> rather than a dev dependency. Becuase ive been attempting to develop locally. And it does not work like this

@Sparticuz
Copy link
Owner

Would you mind sharing where you're sourcing these binaries @Sparticuz?

https://github.com/Sparticuz/chromium/tree/master/_/ansible

@kaykhan
Copy link

kaykhan commented Jan 28, 2023

Im still experiecing this problem locally running sls invoke local -f <function_name>

package.json

  "dependencies": {
    "@sparticuz/chromium": "^110.0.0",
    "puppeteer-core": "19.6.0",
    "puppeteer-extra": "^3.3.4",
    "puppeteer-extra-plugin-stealth": "^2.11.1",
    ....
  },

code

const puppeteer = require("puppeteer-extra");
const chromium = require("@sparticuz/chromium");

const StealthPlugin = require("puppeteer-extra-plugin-stealth")();
StealthPlugin.enabledEvasions.delete("iframe.contentWindow");
StealthPlugin.enabledEvasions.delete("navigator.plugins");
puppeteer.use(StealthPlugin);

browser = await puppeteer.launch({
        args: chromium.args,
        defaultViewport: chromium.defaultViewport,
        executablePath: await chromium.executablePath(),
        //headless: chromium.headless,
        ignoreHTTPSErrors: true,
        headless: false,
});

node v18

is there anything obvious you can see im doing wrong?

{
"statusCode": 500,
"body": "{"message":"Failed","error":"Error: Failed to launch the browser process!\n\n\nTROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md\\n\\n at onClose (/home/kay/kay/app/node_modules/puppeteer-core/src/node/BrowserRunner.ts:328:9)\n at Interface. (/home/kay/kay/app/node_modules/puppeteer-core/src/node/BrowserRunner.ts:314:16)\n at Interface.emit (node:events:525:35)\n at Interface.emit (node:domain:489:12)\n at Interface.close (node:internal/readline/interface:536:10)\n at Socket.onend (node:internal/readline/interface:262:10)\n at Socket.emit (node:events:525:35)\n at Socket.emit (node:domain:489:12)\n at endReadableNT (node:internal/streams/readable:1359:12)\n at processTicksAndRejections (node:internal/process/task_queues:82:21)"}"
}

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
3 participants