CS193V dev environment installer hangs at “Installing Claude Code…” (step 16/26)

Installer release release-0.0.2 · Ubuntu 24.04 host (KVM VM) · rootless podman 4.9.3 · data collected 2026-09-26 07:01 UTC

Reported by Tianle Yu (SUNet tianleyu). The hung process was left running and untouched while this was collected.

Summary: during the container build, /home/student/.local/bin/claude --version (the Claude Code 2.1.225 native binary, built on Bun v1.4.0) spins at 100% CPU forever instead of printing a version. It has been running for 1 h 43 min with no syscalls and no network activity.

Probable cause: the VM’s virtual CPU (“Common KVM processor”) only exposes the x86-64-v1 baseline: no SSE4.2, no POPCNT, no AVX/AVX2. Even Bun’s baseline x64 build needs SSE4.2 + POPCNT. The installer doesn’t check CPU instruction sets, and the build step has no timeout, so the build hangs silently instead of failing with a clear message.

1. What the student sees

The installer gets through the podman install, the file download and the first 15 build steps, then stays on this screen with the spinner still moving:

  Building the course container
    This may take a few minutes.
    localhost/cs193v:local
  ⡿ [████████████████████████░░░░░░░░░░░░░░░░]  16/26
     Installing Claude Code...
  ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
  ┃ added 2 packages in 6s                                              ┃
  ┃ npm warn allow-scripts 1 package has install scripts not yet cover… ┃
  ┃ npm warn allow-scripts   @anthropic-ai/claude-code@2.1.225 (postin… ┃
  ┃ npm warn allow-scripts                                              ┃
  ┃ npm warn allow-scripts Run `npm approve-scripts --allow-scripts-pe… ┃
  ┃ + su student -s /bin/sh -c npm cache clean --force                  ┃
  ┃ npm warn using --force Recommended protections disabled.            ┃
  ┃ + /home/student/.local/bin/claude --version                         ┃
  ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

The spinner never stops, so from the student’s side it looks like a slow step, not a failure. Nothing on screen hints that it will never finish.

2. Environment

Host OSUbuntu 24.04.5 LTS, kernel 6.8.0-45-generic x86_64
VirtualizationKVM (full), systemd-detect-virt = kvm
CPU model“Common KVM processor” (family 15, model 6, stepping 1), 2 vCPUs
x86-64 level (per glibc ld.so)v1 only — v2 / v3 / v4 all not supported
Memory / disk3.8 GiB RAM (3.2 GiB available) · 14 GB free on /
Podman4.9.3 (go1.22.2), rootless, cgroup v2 (systemd), crun 1.14.1, slirp4netns networking
Installercurl -fsSL cs193v.stanford.edu/cs193v-dev/files/install-cs193v.sh | bash → release-0.0.2
Container baseUbuntu 26.04 LTS (glibc)
Claude Code@anthropic-ai/claude-code 2.1.225 → claude-code-linux-x64 (glibc variant, correct for the base)
Binarybin/claude.exe, 297,831,432 bytes, ELF x86-64, not stripped
BuildID 433066516d42fe55315fdc10a614b61c2836d8f6
sha256 0a3be8d18cb0f5357d38ce2d588601753a60b44cc9c622579ed8b8405dee231e
embedded runtime: Bun v1.4.0 (contains string bun-linux-x64-baseline)

CPU flags exposed to the VM

fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx
fxsr sse sse2 ht syscall nx lm constant_tsc nopl xtopology cpuid tsc_known_freq pni
cx16 x2apic hypervisor lahf_lm cpuid_fault pti
sse4_2missing
popcntmissing
avx / avx2 / avx512fmissing
bmi1 / bmi2 / fma / lzcnt / movbemissing
sse / sse2 / pni (sse3) / cx16 / lahf_lmpresent

3. Evidence that it is a spin, not a slow download

PID    PPID   STAT  STARTED (UTC)        ELAPSED   %CPU  WCHAN             COMMAND
43622  43436  Sl+   2026-09-26 05:16:24  01:44:44   1.6  futex_wait_queue  podman build ... -t localhost/cs193v:local
60900  43622  Sl+   2026-09-26 05:19:31  01:41:37   0.3  futex_wait_queue   \_ buildah-oci-runtime
60911  60900  Ss    2026-09-26 05:19:31  01:41:37   0.0  do_wait                \_ /bin/sh -c set -eux; su student ... npm install -g ...; /home/student/.local/bin/claude --version
61320  60911  Rl    2026-09-26 05:19:38  01:41:30  99.8  -                          \_ /home/student/.local/bin/claude --version
60913  43622  S     2026-09-26 05:19:31  01:41:37   0.0  do_poll           \_ slirp4netns ...
14.99%  0x3910081      8.85%  0x1c6750d      8.85%  0x3910050
 8.15%  0x1c674d2      7.95%  0x1c674fa      7.95%  0x3910088
 7.85%  0x3b96544      7.34%  0x1c674bb      7.04%  0x1c674b0
 7.04%  0x3910056      7.04%  0x391007a      6.84%  0x3910064

These are non-PIE virtual addresses in the binary above (BuildID given), so they can be symbolized against it. The binary isn’t stripped. There was no gdb/addr2line on this box, and I didn’t want to attach a debugger to the live process.

4. Analysis

  1. It’s not a wrong-binary problem. bin/claude.exe is a hard link (same inode) to node_modules/@anthropic-ai/claude-code-linux-x64/claude, the glibc x64 build, which matches the Ubuntu 26.04 base. The npm warn allow-scripts … postinstall lines appear, but the link that install.cjs creates is there, so the warning doesn’t seem to be the problem.
  2. It’s not networking or podman. Steps 1–15 ran fine in the same build, including other native binaries. At step 15 the Codex binary (a musl static build) ran --version without trouble.
  3. The CPU is below what the runtime targets. Bun’s standard x64 build targets Haswell-class CPUs (AVX2). Its baseline build targets Nehalem-class CPUs, which still need SSE4.2 and POPCNT. This vCPU has neither, so it’s below both targets. On CPUs that are too old, Bun normally crashes with SIGILL. Here it spins silently instead, which may be the runtime’s fallback or feature-detection path looping when the expected CPU features are missing. That last step is a hypothesis; the missing CPU features are measured.
  4. The build has no timeout, so one hung --version blocks the whole install indefinitely, and the progress UI keeps animating.

5. Timeline (UTC, 2026-09-26)

05:15:57installer started (course-install.sh … release-0.0.2); podman + uidmap installed; course files fetched
05:16:24cs193v --rebuild → podman build started
05:19:31STEP 16/25 (npm install -g @anthropic-ai/claude-code@2.1.225) started
05:19:38claude --version started → began spinning
05:51(unrelated) Docker installed on the host for a separate service. This was 32 minutes after the hang began, so it isn’t the cause.
07:01data collected; process still at 99.8% CPU, state R

6. Reproduction

# On any x86-64 VM whose vCPU lacks SSE4.2/POPCNT (e.g. QEMU/KVM with a
# generic CPU model such as qemu64/kvm64 instead of "host"):
curl -fsSL cs193v.stanford.edu/cs193v-dev/files/install-cs193v.sh | bash

# Quick pre-check on the machine:
grep -o -w -E 'sse4_2|popcnt|avx2' /proc/cpuinfo | sort -u
/lib64/ld-linux-x86-64.so.2 --help | grep x86-64-v   # look for "(supported, searched)"

Faster isolated repro (untested here, since I didn’t want to disturb the running build): in the same image, run timeout 30 /home/student/.local/bin/claude --version; echo $?. On an affected CPU it should exit 124 (timed out) instead of printing 2.1.225.

7. Suggested fixes for the installer

  1. Check the CPU up front, in “Looking at your computer”: on x86_64, require sse4_2 and popcnt in /proc/cpuinfo (x86-64-v2). If they’re missing, fail with a plain message, e.g. “Your CPU (or your VM’s virtual CPU) is too old for Claude Code. If this is a VM, set its CPU type to host or at least x86-64-v2.”
  2. Time-box the version checks in the Containerfile: timeout 120 /home/student/.local/bin/claude --version (and the same for Codex etc.), so a hang becomes a build failure with a log line instead of an endless spinner.
  3. Add a stall detector to the progress meter: if a step’s output hasn’t changed for N minutes, say so and point to the log file (/tmp/cs193v-build-*.log).
  4. Minor inconsistency: step 16 runs /home/student/.local/bin/claude --version as root (HOME=/root), while step 15 runs the Codex check via su student. This probably isn’t related to the hang, but it’s worth making consistent.

8. Workaround for affected students

Change the VM’s CPU model to host (or x86-64-v2/newer), reboot, then rerun the installer. Physical machines from roughly 2009 onward (Intel Nehalem / AMD Bulldozer and later) aren’t affected.

Appendix: build log tail (/tmp/cs193v-build-8cb2c627ad3e.log, 156,842 bytes, last write 05:19)
+ su student -s /bin/sh -c npm install -g '@openai/codex@0.148.0'

added 2 packages in 8s
+ su student -s /bin/sh -c npm cache clean --force
npm warn using --force Recommended protections disabled.
+ su student -s /bin/sh -c /home/student/.local/bin/codex --version
+ grep -qF 0.148.0
+ CODEX_BIN=/home/student/.local/lib/node_modules/@openai/codex/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/bin/codex
+ uname -m
+ WANT_ELF=3e00
+ test 3e00 = 3e00
--> bb34351f5ea6
STEP 15/25: ARG CLAUDE_CODE_VERSION=2.1.225
--> c58008dc73f7
STEP 16/25: RUN set -eux;     su student -s /bin/sh -c "npm install -g '@anthropic-ai/claude-code@${CLAUDE_CODE_VERSION}'";     su student -s /bin/sh -c 'npm cache clean --force';     /home/student/.local/bin/claude --version
+ su student -s /bin/sh -c npm install -g '@anthropic-ai/claude-code@2.1.225'

added 2 packages in 6s
npm warn allow-scripts 1 package has install scripts not yet covered by allowScripts:
npm warn allow-scripts   @anthropic-ai/claude-code@2.1.225 (postinstall: node install.cjs)
npm warn allow-scripts
npm warn allow-scripts Run `npm approve-scripts --allow-scripts-pending` to review, or `npm approve-scripts <pkg>` to allow.
+ su student -s /bin/sh -c npm cache clean --force
npm warn using --force Recommended protections disabled.
+ /home/student/.local/bin/claude --version

The meter reports 16/26 while podman reports 16/25. That’s expected: the meter adds one step for container creation.

Appendix: /proc/61320/status (selected)
Name:   claude
State:  R (running)
NSpid:  61320   40
Threads:        2
VmPeak:  9808104 kB
VmRSS:     29524 kB
Cpus_allowed_list:      0-1
voluntary_ctxt_switches:        20
nonvoluntary_ctxt_switches:     164956
utime_ticks=609889 stime_ticks=297 (CLK_TCK=100)