From 27804b70cf5dfb0d4d05d97c4306cfdfcc19aff4 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Wed, 25 Mar 2026 13:48:45 +0000 Subject: [PATCH] fix(studio): clear bun cache on failure and retry before falling back to npm bun's package cache can become corrupt, storing only package metadata (package.json, README) without actual content (bin/, lib/). When this happens, bun install exits 0 and reports packages as installed, but binaries like tsc are missing from node_modules/.bin/. Changes (both setup.sh and setup.ps1): - After bun install, verify tsc and vite exist in node_modules/.bin/ - If missing, clear the bun cache with bun pm cache rm and retry once - Only fall back to npm if the retry also fails - setup.ps1: check for both tsc and tsc.cmd (Windows creates .cmd wrappers) --- studio/setup.ps1 | 28 +++++++++++++++++++++++++++- studio/setup.sh | 43 ++++++++++++++----------------------------- 2 files changed, 41 insertions(+), 30 deletions(-) diff --git a/studio/setup.ps1 b/studio/setup.ps1 index d8465fd039..34af2d4a61 100644 --- a/studio/setup.ps1 +++ b/studio/setup.ps1 @@ -919,11 +919,37 @@ if ($NeedFrontendBuild -and -not $IsPipInstall) { $UseBun = $null -ne (Get-Command bun -ErrorAction SilentlyContinue) + # bun's package cache can become corrupt -- packages get stored with only + # metadata but no actual content (bin/, lib/). When this happens bun install + # exits 0 but leaves binaries missing. We validate after install and clear + # the cache + retry once before falling back to npm. if ($UseBun) { Write-Host " Using bun for package install (faster)" -ForegroundColor DarkGray & bun install *> $null $bunExit = $LASTEXITCODE - if ($bunExit -ne 0) { + # On Windows, .bin/ entries can be tsc, tsc.cmd, or tsc.ps1 + $hasTsc = (Test-Path "node_modules\.bin\tsc") -or (Test-Path "node_modules\.bin\tsc.cmd") + $hasVite = (Test-Path "node_modules\.bin\vite") -or (Test-Path "node_modules\.bin\vite.cmd") + if ($bunExit -eq 0 -and $hasTsc -and $hasVite) { + # bun install succeeded and critical binaries are present + } elseif ($bunExit -eq 0) { + Write-Host " bun install exited 0 but critical binaries are missing, clearing cache and retrying..." -ForegroundColor Yellow + if (Test-Path "node_modules") { + Remove-Item "node_modules" -Recurse -Force -ErrorAction SilentlyContinue + } + & bun pm cache rm *> $null + & bun install *> $null + $bunExit = $LASTEXITCODE + $hasTsc = (Test-Path "node_modules\.bin\tsc") -or (Test-Path "node_modules\.bin\tsc.cmd") + $hasVite = (Test-Path "node_modules\.bin\vite") -or (Test-Path "node_modules\.bin\vite.cmd") + if ($bunExit -ne 0 -or -not $hasTsc -or -not $hasVite) { + Write-Host " bun retry failed, falling back to npm" -ForegroundColor Yellow + if (Test-Path "node_modules") { + Remove-Item "node_modules" -Recurse -Force -ErrorAction SilentlyContinue + } + $UseBun = $false + } + } else { Write-Host " [WARN] bun install failed (exit $bunExit), falling back to npm" -ForegroundColor Yellow if (Test-Path "node_modules") { Remove-Item "node_modules" -Recurse -Force -ErrorAction SilentlyContinue diff --git a/studio/setup.sh b/studio/setup.sh index 90631f6131..c095fc7245 100755 --- a/studio/setup.sh +++ b/studio/setup.sh @@ -164,20 +164,11 @@ fi echo "✅ Node $(node -v) | npm $(npm -v)" # ── Install bun (optional, faster package installs) ── -# Try the official bun installer first (gives a real bun runtime). -# Fall back to npm install -g bun (gives a shim that may be outdated). -# If neither works, bun is simply skipped and npm handles everything. +# Uses npm to install bun globally -- Node is already guaranteed above, +# avoids platform-specific installers, PATH issues, and admin requirements. if ! command -v bun &>/dev/null; then echo " Installing bun (faster frontend package installs)..." - if curl -fsSL https://bun.sh/install 2>/dev/null | bash > /dev/null 2>&1; then - export BUN_INSTALL="${BUN_INSTALL:-$HOME/.bun}" - export PATH="$BUN_INSTALL/bin:$PATH" - fi - if ! command -v bun &>/dev/null; then - # Official installer failed or unavailable, try npm shim - npm install -g bun > /dev/null 2>&1 || true - fi - if command -v bun &>/dev/null; then + if npm install -g bun > /dev/null 2>&1 && command -v bun &>/dev/null; then echo " bun installed ($(bun --version))" else echo " bun install skipped (npm will be used instead)" @@ -216,11 +207,11 @@ trap _restore_gitignores EXIT # run_quiet calls exit on failure, which would kill the script before the npm # fallback can run. Instead we capture output manually and only show it on failure. # -# IMPORTANT: bun install can exit 0 but silently fail to install packages. -# The npm "bun" shim (v1.3.x) is known to do this. After bun install reports -# success, we verify that critical binaries (tsc, vite) actually landed in -# node_modules/.bin/. If they are missing we reinstall bun from the official -# source and retry once before falling back to npm. +# IMPORTANT: bun's package cache can become corrupt -- packages get stored +# with only metadata (package.json, README) but no actual content (bin/, +# lib/). When this happens bun install exits 0 but leaves binaries missing. +# We verify critical binaries after install. If missing, we clear the cache +# and retry once before falling back to npm. _try_bun_install() { local _log _exit_code=0 _log=$(mktemp) @@ -249,18 +240,12 @@ if command -v bun &>/dev/null; then if _try_bun_install; then _bun_install_ok=true else - # First attempt failed -- try reinstalling bun from official source and retry - echo " Reinstalling bun from bun.sh and retrying..." - if curl -fsSL https://bun.sh/install 2>/dev/null | bash > /dev/null 2>&1; then - export BUN_INSTALL="${BUN_INSTALL:-$HOME/.bun}" - export PATH="$BUN_INSTALL/bin:$PATH" - hash -r 2>/dev/null || true - fi - if command -v bun &>/dev/null; then - echo " bun reinstalled ($(bun --version)), retrying..." - if _try_bun_install; then - _bun_install_ok=true - fi + # First attempt failed, likely due to corrupt cache entries. + # Clear the cache and retry once. + echo " Clearing bun cache and retrying..." + bun pm cache rm > /dev/null 2>&1 || true + if _try_bun_install; then + _bun_install_ok=true fi fi fi