Choosing between browserNoActivityTimeout and captureTimeout for CI flake reduction
0 reputation · 20 Sept 2026, 01:31 UTC
0 reputation · 20 Sept 2026, 01:31 UTC
Karma's browserNoActivityTimeout and captureTimeout both govern how long the runner waits before treating a browser as unresponsive, yet they trigger at different stages of the test lifecycle. A CI pipeline needs deterministic job termination without failing legitimate slow tests, but the two settings interact in ways the documentation does not fully disambiguate.
Lowering browserNoActivityTimeout fails fast when a browser stalls during test execution, reducing hung jobs. However, it can also abort tests that are genuinely slow—such as large integration suites or tests that wait for async operations—producing false negatives. Raising captureTimeout gives browsers more time to start and connect, which helps on resource-constrained CI agents, but it extends the window before a launch failure is detected, potentially masking environment issues.
Because default values and flag handling have shifted across Karma major versions, a configuration that works on one release may behave differently on another. The trade-off is therefore version-sensitive and environment-dependent.
34775 reputation · 20 Sept 2026, 11:33 UTC
browserNoActivityTimeout is the primary lever for preventing indefinite CI hangs. It watches the test runner after the browser has connected. captureTimeout only affects startup and should be set long enough for the slowest agent but not so high that launch failures are hidden.
captureTimeout (default ~60s in Karma 6) is the maximum time Karma will wait for a browser to launch and report ready. It does not kill a browser that is already running but stalled.browserNoActivityTimeout (default ~10s in Karma 6) is the maximum period of inactivity after the browser has started. If no messages are received from the browser during this window, Karma terminates the session, which stops hung tests but can also cut off legitimately slow tests.From Karma 6 onward the defaults changed: browserNoActivityTimeout was lowered to 10s and captureTimeout to 60s. If you upgraded from an older release, re-examine both values; a configuration that once worked may now be too aggressive.
karma start to browser ready)Choose a value that exceeds the slowest observed start-up by ~30%. Common practice is 90–120s on resource-constrained agents.
captureTimeout: 120000 // 120sStart with 30s. This is a safe compromise: it kills a stalled test quickly but still allows slow integration tests that legitimately wait (e.g., 20s async call) to finish.
browserNoActivityTimeout: 30000 // 30sRun the unit suite again. If no failures appear and the job finishes within the expected window, the new timeouts are acceptable for fast tests.
Run the integration suite. Verify that:
browserNoActivityTimeout.If integration tests still fail unnecessarily, increase browserNoActivityTimeout in 5s increments until the failure rate drops, then re-run the unit suite to ensure no new flakiness is introduced.
What is the longest observed browser start-up time on your CI agents? If it regularly exceeds 90s, raise captureTimeout accordingly; otherwise keep it low to surface startup problems early.
To confirm that browserNoActivityTimeout works, add a test that blocks the message loop for 60s:
it('blocks message loop', async () => {
await new Promise(resolve => setTimeout(resolve, 60000));
});When run with browserNoActivityTimeout: 30000, the job should terminate after ~30s, proving the setting is effective.
For deterministic CI termination, prioritize browserNoActivityTimeout and keep captureTimeout just long enough for the slowest browser to launch. Validate with a two-phase test run and adjust incrementally, always checking that fast unit tests stay fast while slow integration tests are not prematurely aborted.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.