DEV Community

Cover image for 3 patterns broke when I ran Claude Code unattended for 7 days
Mirza Iqbal
Mirza Iqbal

Posted on

3 patterns broke when I ran Claude Code unattended for 7 days

API Error: 400 messages.N.content.M: `thinking` blocks in the latest
assistant message cannot be modified. These blocks must remain as they
were in the original response.
Enter fullscreen mode Exit fullscreen mode

That error ended a session I was not watching.

168 hours. 47 sessions. Claude Code running real grinds while I slept, traveled, and worked on other things.

Three patterns broke over the week. None of them were the failure I expected going in.

Here is the strongest thing I took away.

Loud crashes were the failures I worried about. They were rarely the ones that hurt.

What actually hurt looked like forward motion while it quietly destroyed work or stalled the queue.

I run automation like this for a living, across DACH enterprise deployments, and the same three shapes keep showing up. Naming them is most of the fix.

Pattern one. The turn that poisons itself

This was the unexpected one.

With extended thinking on, every assistant turn carries a thinking block that must round-trip back to the model byte for byte on the next request.

Interrupt that turn at the wrong moment, or let an automatic compaction rebuild the history, and the block comes back changed.

Then the server rejects the whole request. Your turn dies. Your run stops.

What surprised me is that nothing in my own tooling could catch it.

That error returns at the transport layer, after the turn has already failed.

My hooks fire around tools and sessions. They never fire around a failed API request.

So the instinct to write a guard that catches it and retries is a dead end. There is no event to hang the guard on.

Here is the real fix. You cannot script your way out of this one. It is a discipline.

Do not resume a turn you interrupted mid-thought. Rebuild the history cleanly, or start fresh, before you continue.

Sit with the cheaper lesson underneath. Some of the most expensive failures cannot be automated around. You can only avoid them.

Pattern two. The cliff at 83 percent

This second pattern cost me the most actual work.

My longest grind committed its progress rarely. One checkpoint every few hours of running.

That feels fine while it runs. It is a trap.

When the rate-limit cap exhausted partway through, the resume point sat hours behind the real progress.

One grind of more than 800 items stalled at 83 percent. Roughly 17 percent of the work was momentum I had to win back by hand.

Run the math and it is plain. Commit once every few hours, and any interruption at hour three erases hours.

This fix is mechanical. How often you commit becomes a property of the loop, something the loop handles on its own so you never have to remember.

Bind the resume cost to a small fixed number of items. A cap exhaustion or a crash then costs you that small number of items. Your afternoon stays safe.

This is the pattern I now refuse to start a long loop without.

Pattern three. The ghost lock

Quietest of the three, and the one that looked most like everything was fine.

Each worker reserved its slot with a lock file. Standard practice for stopping two runs from colliding.

One run got killed hard. The lock file stayed behind, with a dead process id inside it.

My queue then did exactly what it was told. It saw a reservation and waited.

Nothing was running. Nothing was progressing. The dashboard looked busy.

It sat blocked for around 70 minutes before the stale lock aged out on a timer.

Make the lock aware of the thing it protects, and the problem disappears.

Any lock that names a process should release the moment that process is gone. Waiting for a clock to run down is the slow, expensive path.

Reap on death. Keep the timeout only as a backstop.

One thread connects all three

Look at the three together and the shared shape is obvious.

A loud failure is a gift. You see it, you fix it, you move on.

Dangerous failures in an unattended run wear the costume of progress.

A poisoned turn that stops a session you were not watching.

A grind that commits so rarely it gives back hours on the first interruption.

A queue that waits politely on a worker that already died.

Every one of them looked, from the outside, like a healthy system.

Here is the real lesson of running a thing for a week with nobody watching.

Your monitoring is tuned for the errors that shout. The ones that cost you are the errors that smile.

What I am not pasting here

I run a version of each fix in production. The exact instrumentation, the commit-interval numbers, and the runbook that maps each failure shape to a first response are the work I bring to client engagements.

Leaving them out is on purpose.

Paste the implementation, and the next person to hit this copies it and never has the conversation that surfaces the deeper problem underneath.

That conversation is where the real damage gets caught.

Pattern is the gift. Recipe is the work.

Your turn

You have left an agent or a long job running unsupervised at some point.

Something broke while you were not looking.

Which of these three did you hit, and what would you name the one I missed?

Drop the shape you saw in the comments.

Our shared library of failure modes only gets sharper when more of us name the thing out loud.

Top comments (0)