a month ago
Hi Railway team,
I'm running a Node.js service (Puppeteer + system Chromium via apt) that consistently fails to launch the browser process. I've ruled out the common causes and would appreciate help identifying whether this is a platform-level sandboxing restriction.
Service: line-quotation-bot (production)
Symptom: puppeteer.launch() fails every time with "Failed to launch the browser process!" The stderr only shows benign/expected container noise (dbus socket unavailable, crashpad cpufreq file missing) which are known non-fatal warnings in containerized Chromium.
What I've already ruled out with hard evidence:
- Memory — confirmed hundreds of GB free, Node process using ~115MB
- Process/thread limits — checked cgroup pids.max (1000) vs pids.current (11-18), nowhere near the limit
- Corrupted/missing Chromium binary —
chromium --versionruns successfully and returns a valid version string - DevTools WebSocket/port issue — switched Puppeteer to
pipe: true(stdio-based transport instead of a local TCP port), and the browser process now launches AND Puppeteer successfully connects to it
What actually happens: Immediately after Puppeteer connects via pipe and sends its first CDP command (Target.setDiscoverTargets), the connection closes and Puppeteer reports Protocol error (Target.setDiscoverTargets): Target closed. When I run Chromium directly (bypassing Puppeteer entirely) with --headless=new --no-sandbox --disable-gpu --dump-dom about:blank, the process crashes immediately with signal SIGTRAP (not SIGSEGV/SIGABRT — no clean exit code).
This pattern (process starts, immediately traps/crashes on actual headless rendering) looks consistent with a seccomp/sandbox restriction blocking a syscall Chromium needs even with --no-sandbox passed (which only disables Chrome's own internal sandbox, not the host/container-level restrictions).
My question: Does Railway's container runtime apply syscall-level restrictions (e.g., via seccomp or gVisor) that would block Chromium's headless rendering process from starting, even with --no-sandbox? If so, is there a way to relax this for a specific service, or is running headless Chromium directly inside a Railway service simply not supported? I want to confirm before I migrate to an external headless-browser service.
Dockerfile base image: node:20-slim, Chromium installed via apt-get install chromium (currently version 150.x).
Thanks for any insight!
2 Replies
a month ago
This thread has been opened as a bounty so the community can help solve it.
Status changed to Open Railway • about 1 month ago
a month ago
Your diagnosis lines up with a known pattern: SIGTRAP immediately on the first real rendering syscall (not SIGSEGV/SIGABRT), with --no-sandbox making no difference, is the classic signature of a host/runtime-level seccomp restriction — not Chrome's own sandbox. --no-sandbox only disables Chrome's internally-configured sandbox (namespaces + its own seccomp-bpf filter); it can't do anything about syscall filtering imposed by the container runtime itself.
This exact symptom is widely documented on other gVisor-backed platforms (Google Cloud Run is the most-reported case) — Chromium's zygote/renderer processes probe for syscalls that gVisor either doesn't implement or emulates incompletely, and the process traps instead of falling back gracefully.
A few things worth trying to further isolate it before concluding it's unfixable:
- --disable-dev-shm-usage — rules out the classic /dev/shm 64MB-default issue (different failure mode than yours, but cheap to rule out)
- --single-process — if it survives past the crash point, it's likely process/thread-creation syscalls being blocked, not rendering itself
- Try an older Chromium build via apt pin (150.x is very new) — if an older build works, it narrows this to a specific syscall Chromium recently started using
That said, whether Railway's runtime applies gVisor/seccomp restrictions isn't something the community can authoritatively confirm — only Railway can. If it turns out to be platform-level sandboxing, an external headless-browser service (Browserless, ScrapingBee, Steel.dev) is the standard workaround people land on for this exact class of issue on similar platforms.
a month ago
Since Chromium itself is crashing with SIGTRAP outside of Puppeteer, I'd try ruling out the package before assuming it's a Railway restriction.
If you're using the Debian chromium package (150.x), try switching to Chrome for Testing or Puppeteer's bundled Chromium instead. I've seen distro-packaged Chromium behave differently in containers.
Also try adding:
args: [
'--headless=new',
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--single-process',
'--no-zygote',
]
If it still exits with SIGTRAP when running chromium --headless directly, then you've ruled Puppeteer out completely and narrowed it down to Chromium itself or the runtime environment. That makes the next debugging step much clearer.