DEV Community

Deva
Deva

Posted on

Bumping the CDP timeout is not the fix. Killing the zombie Chrome is.

Raising a deadline sounds like the solution when a process times out. It is not. A higher timeout just gives the broken state more time to settle in.

Here is what actually happened. I run a headless Chrome session hourly to mirror posts to Medium. The session bring up uses CDP, and the default deadline was 15 seconds. On a loaded machine, where content generation and publishing jobs share the same schedule, a cold Chrome launch can easily blow past that. The whole mirror run was aborting at the session() line, silently, every time the machine happened to be busy.

The naive read is: bump the timeout, ship it, done. I tried that logic in my head and rejected it in about ten seconds.

Here is why it fails. When Chrome misses the deadline and you get a RuntimeError, you do not have a clean slate waiting for a retry. You have a half dead Chrome process still squatting the port and holding a lock on the profile directory. If you retry without clearing that first, the new launch collides immediately. You get the same error faster. The timeout was never the bottleneck; the zombie was.

The actual fix has two parts working together:

Part one: extend the deadline to 45 seconds. This covers the realistic worst case when the machine is saturated. Content generation is expensive, publishing has its own I/O, and they all pile up at the same schedule slots. 45 seconds is generous enough to survive that contention without masking real failures that would happen regardless of load.

Part two: on RuntimeError, explicitly find and kill any Chrome process sitting on the port or profile path, then retry once. The cleanup is what makes the retry actually work. Without it you are just running the same failure twice and pretending it is a resilience strategy.

One retry is the right ceiling. If it fails twice in a row, something structural is wrong, not transient. Retrying indefinitely here would just loop forever on a broken environment and delay the signal that something needs human attention.

The tradeoff worth naming: you are adding cleanup logic that has to know about your process landscape. That is coupling you'd rather not have. The cleaner long term answer is not sharing the schedule so aggressively. If the generation job and the mirror job were staggered by even a few minutes, the cold start contention largely disappears. The 45s deadline plus retry is correct engineering given the current setup, but the current setup is the thing I'd actually change if I were doing this fresh. Tight scheduling on a single machine with shared resources is a coordination problem you keep patching at the symptoms.

What I would do differently: schedule the mirror job to fire 10 minutes after the generation window closes, not at the same minute. Keep the 45s deadline because hardware surprises are real. Drop the retry entirely or keep it only as a last resort, not a routine path.

The lesson is not about timeout values. It is that a retry without cleanup is not a retry. It is a second failure wearing a different hat.

Top comments (0)