Skip to content

"zsh: bad CPU type in executable" after upgrading to macOS 27

Posted in Macos, Aws, Cli, Debugging

By Dušan Dželebdžić

Photo by Joshua Sortino on Unsplash
Photo by Joshua Sortino on Unsplash

I upgraded my MacBook Air to macOS 27 Golden Gate this week. The next time I needed the AWS CLI, I got this:

zsh: bad CPU type in executable: aws

It had worked the day before. Same laptop, same aws that had been sitting in /usr/local/bin since February 2025.

The CPU hadn't changed overnight. So what had?

What the error is telling you

"Bad CPU type in executable" isn't zsh being dramatic. It's errno 86, EBADARCH, straight from the kernel. The exec call looked at the binary, found no code for this machine's architecture, and refused. zsh just printed the message.

Two commands settle it:

$ uname -m
arm64

$ file "$(readlink -f "$(which aws)")"
/usr/local/aws-cli/aws: Mach-O 64-bit executable x86_64

An Apple silicon Mac and an Intel-only binary. No arm64 slice, not universal.

Which means this aws had never run natively on this laptop. For a year and a half, every aws s3 ls went through Rosetta 2, and I never noticed. That's the whole point of Rosetta, and also why this failure comes as such a surprise.

Rosetta was gone

You can test Rosetta without involving the broken tool at all. /usr/bin/true is a universal binary, so ask for its Intel half:

$ arch -x86_64 /usr/bin/true
arch: posix_spawnp: /usr/bin/true: Bad CPU type in executable

Same error, from a binary Apple ships. That rules out the AWS CLI. The machine can't run Intel code at all.

The runtime lives under /Library/Apple, and after the upgrade mine looked like this:

$ ls /Library/Apple/usr/libexec/oah/
RosettaLinux

Only the piece used for Linux virtual machines was left. The part that translates macOS binaries was missing, and the oahd daemon wasn't running.

My install log says Rosetta was alive and being updated as recently as 20 August:

2026-08-20 01:05:35+02 system_installd[844]: Installed "RosettaUpdateAuto" ()

Then the macOS 27 upgrade ran on the night of 15 September, and the first Rosetta line after it reads like a small obituary:

2026-09-16 00:02:32+02 mbfloagent[1226]: Rosetta flplugin: daemon port null!

It isn't a bug, it's a release note

I assumed the upgrade had gone wrong. It hadn't. Apple's macOS 27 release notes list this under Rosetta, in the Deprecations section:

If Rosetta was previously installed, it is not automatically restored after upgrading to macOS 27.0. (163213094)

One sentence, filed where almost nobody who just wants to run aws will ever look.

Rosetta itself is still supported. Apple's support page says it's available on macOS 27 or earlier. It just doesn't survive the upgrade, and nothing tells you. A GUI app gets a friendly prompt offering to install it. A binary launched from a shell gets errno 86.

The same release notes say where this is heading: "All Intel-based software will no longer be compatible with macOS 28.0, excluding legacy games."

Fix 1: stop needing Rosetta

My CLI was 2.24.11, installed from the official .pkg. Back then that package was Intel-only, on every Mac. AWS started shipping universal macOS installers with 2.30.0 in September 2025. If yours predates that and you never upgraded, you've been running under Rosetta too.

I removed the old install and let Homebrew provide a native one:

sudo rm -rf /usr/local/aws-cli /usr/local/bin/aws /usr/local/bin/aws_completer
brew install awscli
$ aws --version
aws-cli/2.36.47 Python/3.14.7 Darwin/27.0.0 source/arm64

If you'd rather stay on the official installer, download the current AWSCLIV2.pkg and run it over the top. Either way ~/.aws isn't touched, so profiles, SSO sessions and credentials carry over.

One thing to check after a Homebrew install: if the old copy is still in /usr/local/bin and that directory comes first in your PATH, you'll keep hitting the dead binary. which -a aws shows every copy in order.

Fix 2: put Rosetta back

If the broken tool has no native build, reinstall the translator:

softwareupdate --install-rosetta --agree-to-license

On Golden Gate the install prompt comes with a warning that Intel apps won't open on macOS 28. Take it literally. This buys you about a year.

I didn't run it. I had one Intel-only tool on my PATH and a native replacement for it, so bringing back a translation layer with a published end date made no sense.

Find the rest before they find you

The AWS CLI was just the first thing I happened to type. Anything else compiled for Intel only is broken in the same way and will stay quiet until the day you need it.

This lists Intel-only executables in the usual places:

find /usr/local/bin /opt/homebrew/bin ~/.local/bin -maxdepth 1 2>/dev/null | while read -r f; do
t=$(file -bL "$f")
[[ $t == *x86_64* && $t != *arm64* ]] && echo "$f"
done

Mine came back empty once the old CLI was gone. If yours doesn't, the usual suspects are vendor .pkg installers from a few years ago, single-binary tools downloaded from GitHub releases when only the amd64 asset existed, and anything under /usr/local left over from an Intel Homebrew that was migrated from an older Mac.

macOS 27 also lists Intel-based apps under Settings > General. That list is built around apps. I wouldn't trust it to know about a lone binary in /usr/local/bin.

The same errno, wearing a Node costume

That clean scan felt good for about ten minutes. Then I ran this blog's production build to check the post you're reading, and the build died:

 DONE  Compiled successfully

Error: spawn Unknown system error -86
at ChildProcess.spawn (node:internal/child_process:458:11)
...
at NotificationCenter.notifyRaw (node_modules/node-notifier/notifiers/notificationcenter.js:81:11)
at WebpackNotifierPlugin.compilationDone (node_modules/webpack-notifier/index.js:129:14)

Minus 86. Node doesn't have a name for EBADARCH, so you get "Unknown system error" and the raw number. It's the same refusal from the same kernel.

This site still builds its CSS with Laravel Mix 5, which pops a desktop notification when webpack finishes. It does that through node-notifier 9.0.1, which carries its own copy of terminal-notifier inside node_modules:

$ file node_modules/node-notifier/vendor/mac.noindex/terminal-notifier.app/Contents/MacOS/terminal-notifier
.../terminal-notifier: Mach-O 64-bit executable x86_64

The compile had succeeded. The "it worked" toast is what failed, with a non-zero exit, so the Eleventy step after && never ran. One line in webpack.mix.js fixed it:

mix.disableNotifications()

So npm install can plant Intel-only binaries in any project on your disk, and the scan above will never look there. If a Node toolchain starts throwing spawn Unknown system error -86 after the upgrade, read the stack trace for whatever it tried to execute and run file on that.

Takeaway

Nothing was wrong with the AWS CLI. It was an Intel binary that had been quietly translated for eighteen months, and the upgrade removed the translator without saying so.

When something that "used to work fine" dies with bad CPU type in executable right after a macOS upgrade, run file on it before you reinstall anything. If it says x86_64 and nothing else, you've found a tool that was living on borrowed time, and macOS 28 is when the loan gets called in for good.

Replace it now, while it's one binary and not a Monday morning.


Did an OS upgrade break a tool that had worked for years? Send me the error and I'll take a look.