Issue with AWS CDK, TypeScript Lambda, and Lambda Layers – chromium.executablePath
Not a Function
I am working on an AWS Lambda function in TypeScript using AWS CDK for deployment. My Lambda function utilizes Puppeteer and a custom Chromium build to generate PDFs. However, I am encountering a TypeError
related to chromium.executablePath
.
Layer Dependencies:
My package.json
includes the following dependencies for the Lambda Layer:
"dependencies": {
"@sparticuz/chromium": "^106.0.2",
"puppeteer-core": "^18.0.5"
}
Lambda Function:
Here is the relevant part of my Lambda function:
const puppeteer = require("/opt/nodejs/puppeteer-core");
const chromium = require("/opt/nodejs/@sparticuz/chromium");
async function createPdf(fileLinks: Record<string, string>, logoDataUri: string, bucketName: string, key: string): Promise<Buffer> {
await chromium.font("https://raw.githack.com/googlei18n/noto-emoji/master/fonts/NotoColorEmoji.ttf"); // Add Font
const browser = await puppeteer.launch({
args: chromium.args,
defaultViewport: chromium.defaultViewport,
executablePath: await chromium.executablePath(),
headless: chromium.headless,
});
// ... rest of the function
}
// Function logic continues...
Error Encountered:
When invoking the Lambda, I receive the following error:
{
"errorType": "TypeError",
"errorMessage": "chromium.executablePath is not a function",
"trace": [
"TypeError: chromium.executablePath is not a function",
" at createPdf (/var/task/index.js:70735:36)",
" at process.processTicksAndRejections (node:internal/process/task_queues:95:5)",
" at async Runtime.handler (/var/task/index.js:70601:21)"
]
}
CDK Definitions:
Here’s how I defined the layer and the Lambda function in my CDK stack:
this.chromiumLayer = new LayerVersion(this, "chromiumLayer", {
code: Code.fromAsset(join(__dirname, "../../src/layers/chromium")),
compatibleRuntimes: [Runtime.NODEJS_20_X],
compatibleArchitectures: [Architecture.X86_64, Architecture.ARM_64],
description: "Chromium layer for Lambda",
});
this.createDownloadPDF = new NodejsFunction(this, "createDownloadPDF", {
// ... configuration properties
layers: [this.chromiumLayer],
bundling: {
externalModules: ["aws-sdk", "@sparticuz/chromium", "puppeteer-core"],
// ... other bundling options
},
});
tsconfig:
"paths": {
"/opt/nodejs/puppeteer-core": ["./src/layers/chromium/nodejs/node_modules/puppeteer-core"],
"/opt/nodejs/@sparticuz/chromium": ["./src/layers/chromium/nodejs/node_modules/@sparticuz/chromium"]
}
Question:
- Why am I getting the
TypeError: chromium.executablePath is not a function
error? - Is there a specific way to bundle or configure the Lambda layers in AWS CDK for this kind of setup?
- Are there additional steps I need to take to correctly integrate
@sparticuz/chromium
with Puppeteer in a Lambda environment?
Any insights or solutions to address this error would be greatly appreciated. Thank you!
2
Answers
Discoveries
I found that using a
NodejsFunction
offered other problems that I mitigated through using a JS lambda functionWorking Solution:
CDK Code:
Lambda JS Code:
Lambda Layer Package.json:
I tried so many ways and the only one that worked with Nodejs.18+ was to download the chromium binaries at runtime.
This requires no layers, external dependencies, or anything else. The main disadvantage is the cold start: now your lambda needs to download and decompress a ~58MB binary from a remote location (I recommend uploading to S3).
I describe the solution here: https://open.substack.com/pub/konarskis/p/puppeteer-aws-lambda