Claude Code 2.1.252: three silent failures, and the hardening bill

Four fixes, no new features. A Bash output swap refusal that traces straight back to 2.1.251's hardening, an "always allow" that never saved the first time, a Remote Control session frozen by a sick connection rather than a dead one, and a failure notification big enough to blow past the API's 32MB request limit.

claude-code changelog bash permissions

One release since the last digest, 2.1.252 on August 31, and it fits in four lines. All fixes, nothing new. Three days after 2.1.251 and its seventy-odd entries, the contrast is the story: a hardening wave is never finished on the day it ships.

The through-line across these four bugs is not technical, it is diagnostic. Only one of them named itself on screen. The other three showed up as slowness, as clumsiness, or as an error pointing at the wrong culprit. That is exactly the kind of failure you blame on yourself for days before you report it.

The one that spoke up: task output swap refused

Fixed Bash commands failing with "task output swap refused (tasks dir moved or linked)" on some Macs.

That message did not come out of nowhere. 2.1.251 changed, and I quote, "how Bash command output files are created and read back when commands run in the sandbox, so a sandboxed command cannot redirect or replace them." The wording overlaps word for word: the swap being refused here is the replacement that was outlawed there.

The underlying mechanism sits in the tools reference: "Claude Code streams a command's output to a working file as the command runs." That file is the thing worth protecting, since a hostile command that replaces it rewrites what Claude believes it observed. So the new check verifies the tasks directory has been neither moved nor turned into a symlink between two moments.

What the changelog does not justify is the "some Macs" part. Neither the changelog nor the docs explain it, so take what follows for what it is, a hypothesis rather than an established fact: on macOS, the per-user temporary directory lives under /var/folders/..., and /var is itself a link to /private/var. A check that rejects a "linked" directory without resolving the canonical path first will classify a perfectly healthy install as suspicious. Machines that look identical, different verdicts, depending on how TMPDIR got resolved at startup.

This is the most ordinary shape a hardening bug takes, and the hardest to avoid: you write a check against an attacker, and the first person it catches is an ordinary user. At least this one announced itself plainly, cause in parentheses. The next three did not.

The "always allow" that only stuck from the second time on

Fixed "always allow" not saving in a project that has no .claude/settings.local.json yet.

Read the condition closely: no file yet. So the bug only hit the very first "yes, and don't ask again" in a project, which is precisely the action meant to create that file. You approve, nothing objects, and on the next command Claude asks again. No error, no warning. The natural reading is that you misclicked.

The settings docs explain why that first write is its own code path rather than a plain write(): Claude Code creates .claude/settings.local.json "the first time you give a standing approval on a permission prompt," and on that same first pass it adds **/.claude/settings.local.json to your global git excludes file so the file never rides along in a commit. That excludes file is core.excludesFile when your global git config points it at an absolute or ~-prefixed path, otherwise $XDG_CONFIG_HOME/git/ignore, otherwise ~/.config/git/ignore. Creating the file therefore also means touching the machine's git configuration. Far more to get wrong than on the second write.

Concrete consequence if you have been grumbling this week: go reopen the .claude/settings.local.json of your recent projects. The allow rules you thought you had granted may never have landed.

A sick connection is not a dropped connection

Fixed Remote Control sessions hosted by Claude Desktop or VS Code stalling for minutes after a tool finished when the connection to claude.ai was degraded.

The Remote Control docs promise the opposite, and they are explicit: "if your laptop sleeps or your network drops, Claude Code reconnects automatically when your machine comes back online. While the connection is rebuilding, Claude Code queues messages, permission prompts, and status updates from subagents and workflows, and delivers them once the connection recovers."

That guarantee covers the drop. It did not cover the half-alive connection, the one that never declares itself dead and therefore never opens the queue. The symptom is treacherous: the tool finished on your machine, but the result never reaches your phone. Nothing signals a network fault, the indicator stays green. You conclude Claude is slow, or that your request was heavy. Minutes of stall read as normal latency.

It is also the only one of the four fixes aimed at specific hosts, Claude Desktop and the VS Code extension, rather than the terminal session.

32MB, and the error that blamed the wrong thing

Fixed background task notifications with very large failure output (for example git errors on a full disk) making the conversation exceed the API request size limit.

Two ceilings live side by side here, and the gap between them is the whole bug. Locally, the tools reference is generous: "a command whose output passes 5 GB is killed." On the API side, the errors page sets the bar far lower, and names it: Request too large for the API's 32MB request limit.

A background task that fails notifies the conversation, copying its failure output in. As long as that output fits on a screen, nobody thinks twice. A git spiralling into error loops on a full disk produces tens of megabytes in seconds: comfortably under the 5 GB local ceiling, comfortably over the request's 32MB. At which point the conversation becomes unsendable.

The trap is in the advice you get. Faced with Request too large, the docs suggest reducing the number of files, running /compact, removing attachments. Every one of those targets what you put in the conversation. Here the offending block was an automatic notification you never asked for, and /compact could not reach it since it sits in the newest turn. You could prune your context for an hour and unblock nothing.

What to take away

Update, this one is risk free: four fixes, no behaviour to relearn, no new surface to absorb.

The only active step is the second item. If you opened a fresh project with Claude Code this week and granted a standing approval, check that your .claude/settings.local.json exists and actually holds the rule. If not, grant it again; it will stick this time.

And keep the general pattern in mind, because the next big hardening wave will reuse it. Three of these four bugs came dressed as something else: user error, network slowness, an overloaded conversation. When odd behaviour shows up right after a release dense with security fixes, the first place to look is not your config, it is the last three days of changelog.

Pierre Rondeau

Pierre Rondeau

Developer and indie builder. I build products and automations with AI. Creator of Claude Hub.

LinkedIn