We recently ran into a frustrating issue with our screenshot API: Chromium was crashing with a segmentation fault when capturing full-page screenshots of large websites. Here's how we diagnosed and fixed it.
The Problem
Our API uses Playwright with headless Chromium to capture screenshots. For most sites, everything worked fine. But for very tall pages, we'd get this crash:
[pid=422][err] Received signal 11 SEGV_MAPERR 000000000000
Followed by a stack trace and ultimately a RENDER_FAILED error returned to the user. The SEGV_MAPERR with address 000000000000 is a null pointer dereference—Chromium was running out of memory during the screenshot compositing process.
Our Setup
We're running a Spring Boot + Kotlin application with Playwright inside Docker on a Linux VPS. The container was already configured with generous shared memory:
$ docker exec allscreenshots-api df -h /dev/shm
Filesystem Size Used Avail Use% Mounted on
shm 2.0G 0 2.0G 0% /dev/shm
So that wasn't the issue. We also checked if the container had a memory limit:
$ docker exec allscreenshots-api cat /sys/fs/cgroup/memory.max
max
No container limit either—it could use all available host memory.
Finding the Root Cause
The real problem became obvious when we checked the host's actual memory:
$ free -h
total used free shared buff/cache available
Mem: 1.9Gi 1.3Gi 178Mi 26Mi 628Mi 629Mi
Swap: 0B 0B 0B
Only ~630MB available and no swap space. Our 2GB VPS was running Postgres, Caddy, and our application, leaving very little headroom.
To understand why this matters, consider what happens when Chromium takes a full-page screenshot. For a page that's 1920×50,000 pixels at 32-bit color:
1920 × 50,000 × 4 bytes = ~384MB for the raw bitmap alone
Add Chromium's compositing overhead, and you can easily spike to 1GB+ for a single large screenshot. With only 630MB available and no swap, the kernel's OOM killer terminates the process.
The Fix
We added 2GB of swap space:
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# Make it permanent across reboots
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
After enabling swap:
$ free -h
total used free shared buff/cache available
Mem: 1.9Gi 1.3Gi 183Mi 26Mi 631Mi 638Mi
Swap: 2.0Gi 0B 2.0Gi
The large screenshot that was crashing now completes successfully.
Other Things We Considered
Before identifying the root cause, we investigated several other potential fixes:
Increasing Docker's shared memory — Docker defaults to only 64MB for /dev/shm, which is often too small for Chromium. You can increase it in your docker-compose.yml:
services:
your-app:
shm_size: '1gb'
This wasn't our issue since we already had 2GB, but it's a common culprit.
Chrome flags for memory reduction — Playwright already adds many memory-saving flags, but you can add more:
chromium.launch(BrowserType.LaunchOptions().apply {
setArgs(listOf(
"--disable-dev-shm-usage",
"--disable-gpu",
"--disable-software-rasterizer",
"--single-process",
"--memory-pressure-off"
))
})
Reducing screenshot quality — Using JPEG instead of PNG with reduced quality uses less memory during encoding:
page.screenshot(Page.ScreenshotOptions().apply {
setType(ScreenshotType.JPEG)
setQuality(80)
})
Capping maximum height — If you can live with a height limit, this prevents the problem entirely:
val maxHeight = 16384
val actualHeight = (page.evaluate("document.documentElement.scrollHeight") as Number).toInt()
if (actualHeight > maxHeight) {
logger.warn("Page height $actualHeight exceeds max, capping to $maxHeight")
// Return error or take partial screenshot
}
For a screenshot API where full-page capture is a core feature, this wasn't an option for us.
Lessons Learned
Always configure swap on VPS instances running Chromium — Even if you think you have enough RAM, screenshot operations can spike memory usage unpredictably. Swap provides a safety net.
Check actual available memory, not just limits — Container memory limits and shared memory size don't matter if the host itself is constrained.
2GB is tight for a Playwright-based service — If you're running a screenshot API alongside a database and web server, 4GB gives you much more breathing room.
The
SEGV_MAPERR 000000000000error is usually OOM — When you see Chromium crash with a null pointer dereference during screenshot operations, think memory first.
Monitoring Going Forward
We're now keeping an eye on swap usage to know when it's time to upgrade:
free -h | grep Swap
If swap is constantly in use, that's a signal the VPS needs more RAM.
Have you run into similar issues with Playwright or Puppeteer? We'd love to hear about your experience in the comments.
Top comments (0)