
Claude Code SessionEnd Hooks Fixed: No More 1.5s Teardown Cuts
We break down a Claude Code bug that caused SessionEnd hooks to be killed after just 1.5 seconds, even when a global timeout was set, leading to truncated teardowns, missing uploads, and corrupted logs. The episode also covers the fix, best practices for per-hook timeouts, and related updates for gateway pricing sync and OpenTelemetry exports.
Chapter 1
Fixing Truncated Teardowns with CLAUDE CODE SESSIONEND HOOKS TIMEOUT MS
Lachlan Reed
You run a headless CI pipeline or wrap up a long terminal session, everything reports zero errors, but... wait, where did the audit logs go?
James Turner
Yeah, or the transcript upload just completely vanishes. Everything looks like a clean exit on the surface, but your post session cleanup got quietly murdered in the background.
Lachlan Reed
Brought to you by Jellypod AI, today we are digging into a silent killer in Claude Code sessions that drove me absolutely up the wall in my shed last week.
James Turner
So what was actually happening under the hood? Because people were setting the environment variable CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS expecting it to give their heavy cleanup scripts extra time, right?
Lachlan Reed
Spot on. But due to a bug, if your individual SessionEnd hook did not have an explicit per hook timeout property written right inside its config, Claude Code just ignored that environment variable entirely and hard killed the script after a strict 1.5 seconds.
James Turner
One point five seconds! That is barely enough time to spawn a node process, let alone compress a multi megabyte log file or sweep an entire git worktree.
Lachlan Reed
It is ridiculously tight! I had a custom bash script designed to sync local session telemetry and compress my build logs. It kept getting yanked mid write, leaving me with corrupted files or missing uploads, and no error message saying why.
James Turner
But the latest patch finally fixes this. Now, setting CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS properly overrides that default 1.5 second limit for all SessionEnd lifecycle hooks that lack an explicit per hook timeout.
Lachlan Reed
So if you stick CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS=10000 into your GitHub Actions workflow or your local shell profile, your teardown script gets a full ten seconds to wrap up cleanly.
James Turner
Though there is an operational caveat here. You still want to be careful setting massive global timeouts. If a teardown script hangs because of a deadlock or a broken network socket, your terminal exit is going to sit there hanging too.
Lachlan Reed
Yeah, nobody wants to hit exit and wait thirty seconds for their prompt to return! So best practice is still setting specific per hook timeouts where you can, and using the global env var as a reliable baseline cap for the team.
James Turner
Exactly. In our dev containers, we established a team wide ten second cap using that environment variable. It gives telemetry scripts enough runway to finish uploading without letting runaway processes hijack the developer's shell.
Lachlan Reed
While we are on the topic of observability and infrastructure updates in this release, there are two other big additions worth bumping into your stack.
James Turner
Right, if you run enterprise gateways, setting pricing: inside your gateway.yaml file now syncs managed settings directly to signed in Claude Code clients. That means your /cost command and spend meters actually match up with central gateway rates.
Lachlan Reed
And for direct telemetry monitoring, you can now pipe OpenTelemetry trace data straight out by setting OTEL_EXPORTER_OTLP_ENDPOINT directly in your environment.
James Turner
Which means no more lost log uploads, accurate billing rates, and actual traces for your AI tooling pipelines.
Lachlan Reed
Check your session hooks today, raise that timeout, and stop losing your audit logs to the 1.5 second execution cliff.