Native binary hangs silently at 100% CPU on VMs with the kvm64 CPU model (no SSE4/POPCNT) — needs a CPU feature pre-flight check

Open
#95,566 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
55/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
linux, shell

Research direction

Start by inspecting install.sh and the native binary's startup path, then reproduce the hang with qemu-x86_64 -cpu kvm64 and confirm the required CPU features. Done means affected VMs exit promptly with a clear SSE4.2/POPCNT message instead of spinning, with the check covered by an appropriate test or reproduction.

Written by the indexing model from the issue text.

Description

area:installation area:packaging bug has repro platform:linux
Preflight Checklist
  • Searched existing issues (kvm64, "illegal instruction", "Common KVM processor", AVX2, install hang): none.
  • Reproduced with the current version and three older ones.
  • Reproduced with both the glibc (linux-x64) and musl (linux-x64-musl) builds.
What's Wrong?

On a KVM guest whose virtual CPU model is kvm64 — Proxmox VE's default for VMs created from the CLI/API, reported by lscpu as "Common KVM processor" with no sse4_2, popcnt, avx or avx2 flags — claude install (and therefore install.sh) hangs silently: 100% CPU on one core, no output at all (not even "Checking installation status..."), no syscalls, and Ctrl-C is ignored. It never returns. The download and checksum steps of install.sh succeed first, so the user sees a working download followed by a process that does nothing forever.

Nothing points at the CPU. The same binary works on any machine or container with a normal CPU, and it is immune to home directory, environment (env -i), terminal, and locale — all bisected. It took a strace, a gdb backtrace, lscpu, and reproducing the crash under qemu-x86_64 -cpu kvm64 to find it.

Root cause, as far as I can tell: the binary is compiled for a baseline above kvm64 (at least SSE4.2/POPCNT — under emulation with kvm64 it dies with SIGILL). Under real KVM the physical CPU executes those instructions anyway, but CPUID denies them, so CPUID-dispatched code takes inconsistent paths. The spinning frame disassembles to a Latin-1→UTF-8 copy loop that never advances past a byte; the SIMD "first non-ASCII" helper it calls presumably returns a result the scalar path does not expect.

What Should Happen?

Either of:

  1. A pre-flight check in install.sh (grep -q sse4_2 /proc/cpuinfo, and whatever else the build requires) that fails with a clear message: "This CPU does not advertise SSE4.2/POPCNT (model: Common KVM processor). Claude Code's native build requires them. On a VM, set the CPU type to host (Proxmox: qm set <vmid> --cpu host)."
  2. A CPUID check at binary startup that exits with the same message instead of spinning. Bun's own non-baseline builds do this for AVX2; this binary does not, at least not for the features it actually needs.

A 2008-era feature set is not exotic on VMs: it is the default that several hypervisors hand out when nobody chooses a CPU type, so a silent hang here will keep costing people a day each.

Error Messages/Logs

There are none — that is the bug. Evidence gathered by hand:

lscpu on the affected guest:

Model name: Common KVM processor
(no sse4_2, popcnt, avx, avx2 in Flags)

ps while hung:

  PID STAT %CPU WCHAN
30918 Rl+   100 -

strace -f -tt — the main thread's last syscalls return normally, then nothing for minutes; only helper threads keep waking on 30 s futex timeouts:

29502 13:11:34.703449 pread64(6, "1391551 28834 17152 15078 0 1369"..., 256, 0) = 38   # /proc/self/statm
29502 13:11:34.704093 pread64(6, "1391551 28974 17216 15078 0 1369"..., 256, 0) = 38
(no further syscalls from 29502)
29504 13:19:54.809227 futex(0x546ba18, FUTEX_WAIT_PRIVATE, 0, {tv_sec=30, tv_nsec=0}) = -1 ETIMEDOUT

No execve of children, no connect: it never reaches the npm probe or the network.

gdb -p on the musl build (BuildID 6c69c39646afb87ab534c84d789824293b0efac0), thread 1:

#0  0x000000000396cbf5 in ?? ()
#8  0x000000000396bb71 in ?? ()

Disassembly at 0x396cbf5 (non-PIE, so file addresses): a byte-scanning copy loop — cmpb $0,(%r12,%r14) / jscall 250f330 (SIMD first-non-ASCII) … test %r14,%r14; jeand $0xbf,%r14b (Latin-1 → 2-byte UTF-8).

Under user-mode QEMU on this workstation (which itself runs the binary fine):

qemu-x86_64 -cpu kvm64  ./claude install   → exit 132 (SIGILL, core dumped) after 16 s
qemu-x86_64 -cpu qemu64 ./claude install   → exit 132 immediately
qemu-x86_64 -cpu Nehalem ./claude install  → completes
Steps to Reproduce
  1. Create a VM on Proxmox VE (8 or 9) without specifying a CPU type, e.g. qm create 104 --cores 8 --memory 16384 … (defaults to kvm64). Install Ubuntu 24.04.
  2. curl -fsSL https://claude.ai/install.sh | bash
  3. Observe: download and checksum succeed, then "$binary" install sits at 100% CPU with no output. HOME=$(mktemp -d), env -i …, </dev/null >/tmp/o 2>&1 make no difference. Versions 2.1.217, 2.1.252, 2.1.272, 2.1.276 and 2.1.278 all behave the same; so does the musl build.
  4. Fix: qm set 104 --cpu host, restart the VM, re-run the installer — completes normally.

Quick reproduction without a hypervisor: qemu-x86_64 -cpu kvm64 ./claude-2.1.278-linux-x64 install → SIGILL (the emulator enforces CPUID; real KVM does not, hence the hang instead of a crash).

Claude Model

N/A (installer / runtime startup, before any model use)

Is this a regression?

No — every version tried behaves the same.

Last Working Version

None on this CPU model.

Claude Code Version

2.1.278 (also 2.1.276, 2.1.272, 2.1.252, 2.1.217); linux-x64 and linux-x64-musl

Platform

Linux x86-64, KVM guest (Proxmox VE 9), virtual CPU model kvm64

Operating System

Ubuntu 24.04.4 LTS (kernel 6.8), also reproduced under qemu-x86_64 user-mode emulation on the same OS

Terminal/Shell

zsh over ssh; irrelevant — reproduces with no terminal at all

Additional

Happy to test a build with a startup check, or to provide the full strace/gdb output.

Dominant language
TypeScript
Stars
147k
Forks
24k
PR merge metrics
PR metrics pending

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from anthropics/claude-code

All issues in anthropics/claude-code

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.