fix(setup): clear error when setup runs under x86/Rosetta Python (#941)

Add a check_arch() guard that fails fast with actionable guidance when
setup runs on Apple Silicon under an Intel (x86_64) Python via Rosetta —
otherwise compiled deps (bcrypt, pydantic-core, …) load as the wrong
architecture and crash later with a cryptic "incompatible architecture"
import error. Also catch that specific error around the bcrypt import and
print rebuild steps.

Rebased onto current main: the start-macos.sh venv-Python changes that
were part of this branch are dropped, since they're already on main via
PR #978.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Ruben G.
2026-06-07 19:28:37 +03:00
committed by GitHub
parent 681a2a3f2a
commit 55343e89fb
+55 -1
View File
@@ -6,7 +6,9 @@ initial admin user. Safe to re-run (skips what already exists).
"""
import os
import platform
import shutil
import subprocess
import sys
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
@@ -117,7 +119,16 @@ def create_default_admin():
print(f" Temporary password: {password}")
print(f" ** Change it after first login. Set ODYSSEUS_ADMIN_PASSWORD to choose your own. **")
return "created"
except ImportError:
except ImportError as e:
if "incompatible architecture" in str(e).lower():
# bcrypt is present but built for the wrong CPU architecture — the
# same Apple Silicon mismatch check_arch() guards against, caught here
# for the rarer case of an x86 wheel inside an arm64 venv.
print(" [error] bcrypt loaded with the wrong CPU architecture.")
print(" Rebuild the venv with an arm64 Python:")
print(" rm -rf venv && /opt/homebrew/bin/python3.11 -m venv venv")
print(" ./venv/bin/pip install -r requirements.txt")
return "skipped"
print(" [warn] bcrypt not installed — skipping admin user creation")
print(" Run: pip install bcrypt")
return "skipped"
@@ -167,9 +178,52 @@ def check_deps():
print(" [ok] tmux installed")
def check_arch():
"""Stop early, with guidance, if we're on Apple Silicon but running an
Intel (x86_64) Python through Rosetta.
A venv built with such an interpreter installs and loads compiled packages
(bcrypt, pydantic-core, onnxruntime, …) for the wrong CPU architecture, then
dies deep inside an import with a cryptic
"(mach-o file, but is an incompatible architecture)" error. Catching it here
turns that into one clear, actionable message.
"""
if sys.platform != "darwin" or platform.machine() == "arm64":
return # Not macOS, or already an arm64-native interpreter — nothing to do.
# platform.machine() == "x86_64": either a genuine Intel Mac (fine) or an x86
# interpreter running under Rosetta on Apple Silicon (the case we must catch).
try:
translated = subprocess.run(
["sysctl", "-n", "sysctl.proc_translated"],
capture_output=True, text=True, timeout=5,
).stdout.strip()
except Exception:
translated = ""
if translated != "1":
return # Genuine Intel Mac — carry on.
print("\n [error] This is an Apple Silicon Mac, but setup is running under an")
print(" Intel (x86_64) Python through Rosetta. Compiled packages would")
print(' load as the wrong architecture and crash with "incompatible')
print(' architecture" later on.')
print("\n Rebuild the environment with Homebrew's arm64 Python:")
print(" brew install python@3.11 # if you don't have it yet")
print(" rm -rf venv")
print(" /opt/homebrew/bin/python3.11 -m venv venv")
print(" ./venv/bin/pip install -r requirements.txt")
print(" ./venv/bin/python setup.py")
print("\n Tip: ./start-macos.sh does all of this with the right Python.\n")
sys.exit(1)
def main():
print("\n=== Odysseus Setup ===\n")
# Fail fast with a clear message if the CPU architecture is wrong (Apple
# Silicon under an x86/Rosetta Python) before importing anything native.
check_arch()
print("1. Creating directories...")
create_dirs()