imsg is a handy command line tool that reads the macOS Messages database so you can query your iMessages from the terminal. After installing it with Homebrew, you may hit this error the moment you run it:
/usr/local/bin/imsg: line 2: /usr/local/Cellar/imsg/0.5.0/libexec/imsg: Bad CPU type in executable /usr/local/bin/imsg: line 2: /usr/local/Cellar/imsg/0.5.0/libexec/imsg: Undefined error: 0
This post explains what causes it and the fix that actually worked: building a universal binary from source.
What "Bad CPU type in executable" means
That error appears when the architecture of the binary does not match the architecture your shell is running under. On an Intel Mac, or on an Apple Silicon Mac running a terminal under Rosetta, the process expects an x86_64 binary, but the installed imsg binary was built only for arm64 (or vice versa). macOS refuses to run a binary whose CPU type it cannot execute.
Step 1: Confirm the architecture mismatch
Check what architecture your shell is running as:
arch # i386
Then inspect the installed tool. The Homebrew wrapper is just a shell script that execs the real binary:
file /usr/local/Cellar/imsg/0.5.0/bin/imsg # Bourne-Again shell script text executable, ASCII text bash -x /usr/local/Cellar/imsg/0.5.0/bin/imsg # + exec /usr/local/Cellar/imsg/0.5.0/libexec/imsg # .../libexec/imsg: Bad CPU type in executable
So the wrapper runs fine, but the real executable in libexec is the wrong CPU type for this shell.
Step 2: Why reinstalling from the bottle is not enough
The obvious next move is to reinstall, forcing a source build:
brew uninstall imsg brew install --build-from-source imsg
But on inspection the resulting binary was still single-architecture:
file /usr/local/Cellar/imsg/0.5.0/libexec/imsg # Mach-O 64-bit executable arm64
Still arm64, which is exactly the architecture that does not run under an x86 shell. The Homebrew formula build did not produce something this shell could execute.
Step 3: Build a universal binary from source
The reliable fix is to clone the project and use its own build target, which produces a universal binary that contains both arm64 and x86_64 slices. macOS then picks whichever slice matches the running shell.
brew uninstall imsg git clone https://github.com/steipete/imsg.git cd imsg make build
The make build target resolves the Swift package dependencies (Commander, PhoneNumberKit, SQLite.swift), links the tool, and reports a universal binary:
Built /Users/devharsh/Downloads/imsg/bin/imsg (arm64 x86_64)
The (arm64 x86_64) at the end is the important part: this binary runs on Apple Silicon and Intel, natively or under Rosetta, so the "Bad CPU type" error is gone. The project's Makefile exposes a few useful targets:
make format - swift format in-place make lint - swift format lint + swiftlint make test - sync version, patch deps, run swift test make build - universal release build into bin/ make imsg - clean rebuild + run debug binary (ARGS=...) make clean - swift package clean
Step 4: Verify with the test suite
Optionally confirm everything is healthy by running the tests, which build and exercise the package:
make test # Build complete! # Test Suite 'All tests' passed
Step 5: Grant Full Disk Access
Because imsg reads the Messages database, it needs Full Disk Access for your terminal:
- Open System Settings > Privacy & Security > Full Disk Access.
- Enable access for your terminal application (Terminal, iTerm, etc.).
To let it send messages, also allow your terminal to control Messages.app under System Settings > Privacy & Security > Automation.
Summary
"Bad CPU type in executable" is an architecture mismatch. Neither the bottle nor brew install --build-from-source produced a binary this shell could run, because both were single-architecture. Cloning the repo and running make build produced a universal arm64 x86_64 binary that runs everywhere, which resolved the error.
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.