Description
Summary
System Chromium 150 on our GitLab CI runner does not produce a DevTools websocket URL when started via Ferrum/Cuprite. This raises Ferrum::ProcessTimeoutError and, under parallel system specs, eventually causes the CI job to hit its 1 hour timeout.
The same Ferrum configuration works with:
- Chrome for Testing 148 / 149 (CI workaround — pinned download)
- Chrome for Testing 150.0.7871.115 locally (
linux/amd64, 4 parallel workers, ~870 system spec examples, 0 failures, ~9 minutes)
This does not look like a missing process_timeout setting. Chromium 150 appears to hang on startup in our CI environment when using the system browser binary.
Error
Ferrum::ProcessTimeoutError:
Browser did not produce websocket url within 30 seconds, try to increase `:process_timeout`.
When running parallel system specs without a Chrome pin, workers stall after printing seeds. Failures cluster in the spec files assigned to a single hung worker (typical of one browser never starting). The job is eventually killed:
4 processes for 65 specs, ~ 16 specs per process
Randomized with seed 52070
... (long silence, no example output) ...
19 examples, 18 failures
Failed examples:
rspec ./spec/system/example_feature_spec.rb:42 # ExampleFeature does something
rspec ./spec/system/example_feature_spec.rb:58 # ExampleFeature does something else
... (remaining failures all in the same spec file — same parallel worker batch)
WARNING: step_script could not run to completion because the timeout was exceeded.
ERROR: Job failed: execution took longer than 1h0m0s seconds
The individual assertion messages are irrelevant here — every example in that worker’s batch fails because the browser never connects. This is not an application regression.
Secondary noise after the job is killed (not the root cause):
/usr/local/bundle/gems/parallel_tests-5.7.0/lib/parallel_tests/pids.rb:46:in 'IO.read':
No such file or directory @ rb_sysopen - /tmp/parallel_tests-pidfile... (Errno::ENOENT)
Steps to reproduce
Failing case (CI)
- Use a Debian-based
linux/amd64 CI image with system Chromium 150, e.g. chromium --version → 150.0.7871.46.
- Configure Ferrum/Cuprite with headless mode and container flags (
no-sandbox, disable-gpu, disable-dev-shm-usage).
- Point
browser_path at /usr/bin/chromium (no Chrome-for-Testing override).
- Run parallel browser specs (we use
parallel_rspec with 4 workers).
Expected: Chromium starts and Ferrum receives a DevTools websocket URL.
Actual: Browser startup hangs; ProcessTimeoutError after process_timeout; parallel workers fail in batches; job may run until the CI timeout.
Passing case (local)
linux/amd64 container.
- Chrome for Testing 150.0.7871.115 at
/opt/chrome-linux64/chrome.
- Ferrum 0.17.2, Cuprite 0.17, same browser flags.
CI=true, SYSTEM_WORKERS=4, full parallel system suite.
Result: ~870 examples, 0 failures, ~8m 39s.
Workaround (CI)
Download an older Chrome for Testing build and set BROWSER_PATH:
CHROME_VERSION=149.0.7827.155 # 148.x also works
curl -fsSL "https://storage.googleapis.com/chrome-for-testing-public/${CHROME_VERSION}/linux64/chrome-linux64.zip" -o /tmp/chrome.zip
unzip -q -o /tmp/chrome.zip -d /opt
chmod +x /opt/chrome-linux64/chrome
export BROWSER_PATH=/opt/chrome-linux64/chrome
Additional mitigations that helped but did not fix Chromium 150 on CI:
CUPRITE_PROCESS_TIMEOUT=60
SYSTEM_WORKERS=2
Environment
| Component |
Version |
| Ferrum |
0.17.2 (also seen on 0.17.1) |
| Cuprite |
0.17 |
| Ruby |
4.0 |
| parallel_tests |
5.7.0 |
| Capybara |
3.40.0 |
| OS |
Debian, linux/amd64 |
| CI image |
Private GitLab CI runner, Debian-based linux/amd64 builder image with system Chromium 150 |
Chrome / Chromium versions tested
| Browser |
Version |
Source |
Result |
| Chromium |
150.0.7871.46 |
System (/usr/bin/chromium) |
Fails in CI |
| Chrome for Testing |
150.0.7871.115 |
Downloaded binary |
Passes locally |
| Chrome for Testing |
149.0.7827.155 |
Downloaded binary |
Passes in CI (current workaround) |
| Chrome for Testing |
148.0.7778.215 |
Downloaded binary |
Passes in CI |
Configuration
Ferrum options used via Cuprite:
cuprite_options = {
window_size: [1200, 800],
browser_options: {
'no-sandbox' => true,
'disable-gpu' => true,
'disable-dev-shm-usage' => true,
'disable-background-timer-throttling' => true,
'disable-backgrounding-occluded-windows' => true,
'disable-renderer-backgrounding' => true,
'force-color-profile' => 'srgb',
'disable-ipc-flooding-protection' => true
},
pending_connection_errors: false,
process_timeout: Integer(ENV.fetch('CUPRITE_PROCESS_TIMEOUT', 30)),
headless: true
}
cuprite_options[:browser_path] = browser_path if browser_path
JS system specs also retry up to 3 times via rspec-retry, which can make hangs appear as long silent periods before failures.
Minimal reproduction
#!/usr/bin/env ruby
# frozen_string_literal: true
require "ferrum"
browser_path = ENV.fetch("BROWSER_PATH", "/usr/bin/chromium")
puts "Using browser: #{browser_path}"
puts `#{browser_path} --version`
browser = Ferrum::Browser.new(
headless: true,
browser_path: browser_path,
process_timeout: 60,
browser_options: {
"no-sandbox" => nil,
"disable-gpu" => nil,
"disable-dev-shm-usage" => nil
}
)
puts "Browser started"
puts "Version: #{browser.version}"
browser.go_to("about:blank")
puts "OK"
browser.quit
Run in CI:
# Fails
BROWSER_PATH=/usr/bin/chromium ruby repro.rb
# Works (example)
CHROME_VERSION=149.0.7827.155
curl -fsSL "https://storage.googleapis.com/chrome-for-testing-public/${CHROME_VERSION}/linux64/chrome-linux64.zip" -o /tmp/chrome.zip
unzip -q -o /tmp/chrome.zip -d /opt
BROWSER_PATH=/opt/chrome-linux64/chrome ruby repro.rb
What we have ruled out
- Increasing
process_timeout to 60 seconds does not fix system Chromium 150 in CI.
- Upgrading Ferrum from 0.17.1 to 0.17.2 does not fix system Chromium 150 in CI.
- Application regressions are unlikely: the same suite passes locally on Chrome 150 with 0 failures.
- Parallel test databases are set up correctly (
parallel:create, parallel:load_schema).
Questions for maintainers
- Is there a known incompatibility between Ferrum 0.17.x and Chromium 150 on Debian in containerised CI?
- Could Ferrum surface Chrome stderr when startup succeeds but no websocket URL is returned?
- Is the difference between system Chromium 150 and Chrome for Testing 150 a supported/expected distinction?
Related issues
Additional context
We are happy to test patches. The explicit Ferrum::ProcessTimeoutError line is intermittent in archived logs because the latest CI failure ended with a 1-hour job timeout after workers hung, but this matches the failure mode seen when using system Chromium 150 without a Chrome-for-Testing pin.
Description
Summary
System Chromium 150 on our GitLab CI runner does not produce a DevTools websocket URL when started via Ferrum/Cuprite. This raises
Ferrum::ProcessTimeoutErrorand, under parallel system specs, eventually causes the CI job to hit its 1 hour timeout.The same Ferrum configuration works with:
linux/amd64, 4 parallel workers, ~870 system spec examples, 0 failures, ~9 minutes)This does not look like a missing
process_timeoutsetting. Chromium 150 appears to hang on startup in our CI environment when using the system browser binary.Error
When running parallel system specs without a Chrome pin, workers stall after printing seeds. Failures cluster in the spec files assigned to a single hung worker (typical of one browser never starting). The job is eventually killed:
The individual assertion messages are irrelevant here — every example in that worker’s batch fails because the browser never connects. This is not an application regression.
Secondary noise after the job is killed (not the root cause):
Steps to reproduce
Failing case (CI)
linux/amd64CI image with system Chromium 150, e.g.chromium --version→150.0.7871.46.no-sandbox,disable-gpu,disable-dev-shm-usage).browser_pathat/usr/bin/chromium(no Chrome-for-Testing override).parallel_rspecwith 4 workers).Expected: Chromium starts and Ferrum receives a DevTools websocket URL.
Actual: Browser startup hangs;
ProcessTimeoutErrorafterprocess_timeout; parallel workers fail in batches; job may run until the CI timeout.Passing case (local)
linux/amd64container./opt/chrome-linux64/chrome.CI=true,SYSTEM_WORKERS=4, full parallel system suite.Result: ~870 examples, 0 failures, ~8m 39s.
Workaround (CI)
Download an older Chrome for Testing build and set
BROWSER_PATH:Additional mitigations that helped but did not fix Chromium 150 on CI:
CUPRITE_PROCESS_TIMEOUT=60SYSTEM_WORKERS=2Environment
linux/amd64linux/amd64builder image with system Chromium 150Chrome / Chromium versions tested
/usr/bin/chromium)Configuration
Ferrum options used via Cuprite:
JS system specs also retry up to 3 times via
rspec-retry, which can make hangs appear as long silent periods before failures.Minimal reproduction
Run in CI:
What we have ruled out
process_timeoutto 60 seconds does not fix system Chromium 150 in CI.parallel:create,parallel:load_schema).Questions for maintainers
Related issues
process_timeouterrorsBrowser did not produce websocketin CIAdditional context
We are happy to test patches. The explicit
Ferrum::ProcessTimeoutErrorline is intermittent in archived logs because the latest CI failure ended with a 1-hour job timeout after workers hung, but this matches the failure mode seen when using system Chromium 150 without a Chrome-for-Testing pin.