Ask
28

"zsh: bad CPU type in executable" and "mach-o file, but is an incompatible architecture": what is the Mac actually telling me? Architecture

New Mac, moved my work across, and I now get one of these two errors constantly. Sometimes from a command line tool, sometimes when a Python package imports something.

The second one says have 'x86_64', need 'arm64', which at least sounds like a clue, but I do not know which half of my setup is the wrong one or how it got that way.

What I would like:

  1. What is the difference between the two errors, are they the same thing?
  2. How do I find out what architecture something actually is?
  3. Why did this happen when everything installed without complaining?
5 answers Share
Report

Answering anonymously, a moderator will review it first.

  • @rosetta_reva · last mo. · 2 replies

    Same underlying condition, two different layers noticing it.

    "bad CPU type in executable" comes from the system trying to launch a program. You asked to run an Intel binary and there is no translation available for it, usually because Rosetta is not installed.

    "mach-o file, but is an incompatible architecture" comes from something trying to load a library into an already-running process. This one cannot be solved by translation at all: a process is either Intel or ARM for its whole life, and you cannot load an Intel library into an ARM process. The error politely names both sides: have 'x86_64', need 'arm64' means the file on disk is Intel and the process asking for it is ARM.

    That second one is the one that bites Python users, because a native ARM Python is trying to import a package that shipped an Intel binary. There is no flag that fixes it. The package has to be reinstalled for the right architecture, or the whole environment has to run as Intel.

    29
    Share
    Reply

    Answering anonymously, a moderator will review it first.

    Report
    • @arch_mismatch_ami · last mo.

      "A process is either Intel or ARM for its whole life" is the sentence I needed. I had been looking for a way to translate per-library.

      13
      Share
      Reply

      Answering anonymously, a moderator will review it first.

      Report
  • @brew_prefix_bo · last mo.

    For question 2, three commands answer nearly everything in this room:

    uname -m                 # what this shell is: arm64 or x86_64
    file $(which python3)    # what that specific binary contains
    file <path-to-the.so>    # the library in the error message
    

    file prints something like Mach-O 64-bit bundle x86_64 or arm64, and a universal binary lists both.

    The surprise for a lot of people is the first one. If uname -m says x86_64 on an Apple Silicon Mac, your terminal is running under Rosetta: usually because the app has "Open using Rosetta" ticked in Get Info, which somebody turned on years ago to fix something else. Everything you install from that terminal will then be Intel, silently and consistently.

    That one checkbox explains an enormous number of these threads.

    1
    Share
    Reply

    Answering anonymously, a moderator will review it first.

    Report
  • @clt_cassie · last mo.

    Question 3 is the interesting one: nothing complained because at install time nothing was wrong.

    A package manager downloading an Intel build onto a machine that can run Intel builds has no reason to object. Rosetta means Intel binaries do work. The failure only appears at the moment two things of different architectures have to occupy the same process, which can be weeks later and in a completely unrelated command.

    The usual origins, in rough order:

    • A migrated environment. Migration Assistant copies the Intel binaries across faithfully. They ran fine on the old machine and they still run - until something native tries to load one.
    • A virtual environment carried over in a project folder, or restored from a lock file that pins built wheels.
    • A terminal running under Rosetta, as above.
    • Two Homebrews, which is its own thread.

    The cleanest fix for a migrated setup is unsentimental: delete and rebuild the environment on the new machine rather than repairing it. It is faster than it sounds and it ends the whole category.

    1
    Share
    Reply

    Answering anonymously, a moderator will review it first.

    Report
  • @loopback_lior · 4w ago

    If you genuinely need something to stay Intel: a dependency with no ARM build: the supported way is to run the whole thing translated rather than mixing:

    arch -x86_64 zsh
    

    That gives you an Intel shell. Everything launched from it is Intel, and packages installed from it are Intel, consistently. Build your environment there and it will be internally coherent.

    The mistake to avoid is doing this halfway, installing some things from an Intel shell and some from a native one, into the same environment. That produces exactly the mixed state you are debugging now, and it is harder to unpick than starting over.

    1
    Share
    Reply

    Answering anonymously, a moderator will review it first.

    Report