fix(install): replay npm's debug log into the bootstrap stream on failure

On Windows npm prints only a terse summary on failure; the actual cause
(postinstall stderr like Electron's install.js, network traces, EBUSY
retries) lives in npm-cache\_logs\<ts>-debug-0.log, which never reached
the Tauri bootstrap log. Field report: a fresh-VM desktop install died
with 'npm error command node install.js' and zero actionable detail.

Adds Write-NpmDebugLogTail: locates the debug log from npm's 'A complete
log of this run' line (fallback: newest _logs/*-debug-*.log under 'npm
config get cache') and replays its last 200 lines through our output
stream, which the bootstrap installer's streaming sink captures.

Wired at all four npm failure sites: desktop workspace npm ci/install,
_Run-NpmInstall (browser tools), Install-AgentBrowser (--silent global
install), and the desktop 'npm run pack' build step.
This commit is contained in:
Teknium
2026-08-08 22:43:01 -07:00
parent 3a915c46d3
commit 1d45e62f30

View File

@@ -553,6 +553,62 @@ function Show-NpmCertHint {
return $true
}
function Write-NpmDebugLogTail {
# On failure npm prints only a terse summary to stdout/stderr; the real
# evidence (postinstall script stderr like Electron's install.js, network
# traces, EBUSY retries) lives in npm's own debug log under
# <npm-cache>\_logs\<timestamp>-debug-0.log. The bootstrap installer's
# streaming sink only captures what WE emit, so on any npm failure this
# helper locates that debug log and replays its tail into our output
# stream -- making the bootstrap log a self-contained diagnosis instead
# of "exit 1, details in a file on a VM nobody can reach".
param(
[string]$NpmOutput,
[int]$TailLines = 200
)
$logPath = $null
# Preferred: npm names the exact file in its failure summary.
if ($NpmOutput -and $NpmOutput -match "A complete log of this run can be found in:\s*(?<path>[^\r\n]+)") {
$candidate = $Matches['path'].Trim()
if (Test-Path -LiteralPath $candidate) { $logPath = $candidate }
}
# Fallback (covers --silent runs, truncated output): newest debug log in
# npm's cache _logs directory.
if (-not $logPath) {
try {
$npm = Resolve-NpmCmd
if ($npm) {
$prevEAPLocal = $ErrorActionPreference
$ErrorActionPreference = "Continue"
$cacheDir = (& $npm config get cache 2>$null | Select-Object -Last 1)
$ErrorActionPreference = $prevEAPLocal
if ($cacheDir) {
$logsDir = Join-Path ("$cacheDir").Trim() "_logs"
if (Test-Path -LiteralPath $logsDir) {
$newest = Get-ChildItem -LiteralPath $logsDir -Filter "*-debug-*.log" -ErrorAction SilentlyContinue |
Sort-Object LastWriteTime -Descending | Select-Object -First 1
if ($newest) { $logPath = $newest.FullName }
}
}
}
} catch { }
}
if (-not $logPath) {
Write-Warn "npm debug log could not be located -- no further npm detail available"
return
}
$tail = $null
try {
$tail = Get-Content -LiteralPath $logPath -Tail $TailLines -ErrorAction Stop
} catch {
Write-Warn "Could not read npm debug log ${logPath}: $($_.Exception.Message)"
return
}
Write-Warn "---- npm debug log: last $TailLines lines of $logPath ----"
foreach ($line in $tail) { Write-Host " $line" -ForegroundColor DarkGray }
Write-Warn "---- end npm debug log ----"
}
# --- Ensure-mode helpers ---
function Resolve-NpmCmd {
@@ -620,6 +676,9 @@ function Install-AgentBrowser {
Remove-Item $npmLog -Force -ErrorAction SilentlyContinue
Write-Err "npm install -g failed (exit $npmExit): $npmDetail"
Show-NpmCertHint $npmDetail | Out-Null
# This install runs with --silent, so $npmDetail is often near-empty;
# npm's debug log is the only place the real error survives.
Write-NpmDebugLogTail -NpmOutput $npmDetail
throw "npm install failed"
}
Remove-Item $npmLog -Force -ErrorAction SilentlyContinue
@@ -2973,6 +3032,7 @@ function Install-NodeDeps {
}
Write-Info " Full log: $logPath"
Show-NpmCertHint $errText | Out-Null
Write-NpmDebugLogTail -NpmOutput $errText
}
}
Write-Info "Run manually later: cd `"$installDir`"; npm install"
@@ -3344,6 +3404,10 @@ function Install-Desktop {
Try-RestoreElectronDist -InstallDir $InstallDir | Out-Null
} else {
Show-NpmCertHint ($npmOut -join "`n") | Out-Null
# Replay npm's own debug log into our stream: the terse
# summary above rarely contains the postinstall stderr
# (e.g. Electron's install.js) that explains the failure.
Write-NpmDebugLogTail -NpmOutput ($npmOut -join "`n")
throw "desktop workspace npm install failed (exit $code) -- see lines above for cause"
}
} else {
@@ -3465,6 +3529,10 @@ function Install-Desktop {
foreach ($line in $snippet -split "`n") { Write-Host " $line" -ForegroundColor DarkGray }
Write-Info " Full log: $buildLog"
}
# `npm run pack` failures (lifecycle script exits) also land in
# npm's debug log; replay it so the bootstrap log carries the
# full evidence even when $buildLog's tail cuts off the cause.
Write-NpmDebugLogTail -NpmOutput $errText
throw "apps/desktop build failed (exit $code)"
}
Write-Success "Desktop app built"