Skip to content

Commit 9c44d45

Browse files
authored
fix(openclaw): resolve installation failure on Windows with spaces in path (#12977)
### What this PR does Before this PR: - OpenClaw installation/uninstallation failed on Windows when the npm command path contained spaces (e.g., "C:\Program Files\nodejs\npm.cmd"). After this PR: - OpenClawService.install() and OpenClawService.uninstall() use spawn with shell: true when the npm path contains spaces, fixing the Windows installation failure. Fixes #12945, #12935, #12963 ### Why we need it and why it was done in this way - Using spawn with shell:true for npm paths containing spaces ensures the command is executed correctly on Windows without changing crossPlatformSpawn or other callers. - Scope limited to install() and uninstall() to minimize impact. ### Breaking changes - None. ### Special notes for your reviewer - Change is minimal and targeted to OpenClawService install/uninstall logic. ### Checklist - [x] PR: The PR description is expressive enough and will help future contributors - [x] Code: Write code that humans can understand and Keep it simple - [ ] Refactor: Left the code cleaner than you found it - [ ] Upgrade: Impact of this change on upgrade flows was considered - [x] Documentation: No user-guide update required Release note ```release-note fix(openclaw): handle npm paths with spaces on Windows during install/uninstall ```
1 parent 38c29c1 commit 9c44d45

File tree

1 file changed

+14
-6
lines changed

1 file changed

+14
-6
lines changed

src/main/services/OpenClawService.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -247,14 +247,18 @@ class OpenClawService {
247247
// Keep the command string for logging and sudo retry
248248
const npmCommand = `"${npmPath}" install -g ${packageName} ${registryArg}`.trim()
249249

250-
logger.info(`Installing OpenClaw with command: ${npmPath} ${npmArgs.join(' ')}`)
251-
this.sendInstallProgress(`Running: ${npmPath} ${npmArgs.join(' ')}`)
250+
// On Windows, wrap npm path in quotes if it contains spaces and is not already quoted
251+
const needsQuotes = isWin && npmPath.includes(' ') && !npmPath.startsWith('"')
252+
const processedNpmPath = needsQuotes ? `"${npmPath}"` : npmPath
253+
254+
logger.info(`Installing OpenClaw with command: ${processedNpmPath} ${npmArgs.join(' ')}`)
255+
this.sendInstallProgress(`Running: ${processedNpmPath} ${npmArgs.join(' ')}`)
252256

253257
const spawnEnv = await getShellEnv()
254258

255259
return new Promise((resolve) => {
256260
try {
257-
const installProcess = crossPlatformSpawn(npmPath, npmArgs, { env: spawnEnv })
261+
const installProcess = crossPlatformSpawn(processedNpmPath, npmArgs, { env: spawnEnv })
258262

259263
let stderr = ''
260264

@@ -346,14 +350,18 @@ class OpenClawService {
346350
// Keep the command string for logging and sudo retry
347351
const npmCommand = `"${npmPath}" uninstall -g openclaw @qingchencloud/openclaw-zh`
348352

349-
logger.info(`Uninstalling OpenClaw with command: ${npmPath} ${npmArgs.join(' ')}`)
350-
this.sendInstallProgress(`Running: ${npmPath} ${npmArgs.join(' ')}`)
353+
// On Windows, wrap npm path in quotes if it contains spaces and is not already quoted
354+
const needsQuotes = isWin && npmPath.includes(' ') && !npmPath.startsWith('"')
355+
const processedNpmPath = needsQuotes ? `"${npmPath}"` : npmPath
356+
357+
logger.info(`Uninstalling OpenClaw with command: ${processedNpmPath} ${npmArgs.join(' ')}`)
358+
this.sendInstallProgress(`Running: ${processedNpmPath} ${npmArgs.join(' ')}`)
351359

352360
const shellEnv = await getShellEnv()
353361

354362
return new Promise((resolve) => {
355363
try {
356-
const uninstallProcess = crossPlatformSpawn(npmPath, npmArgs, { env: shellEnv })
364+
const uninstallProcess = crossPlatformSpawn(processedNpmPath, npmArgs, { env: shellEnv })
357365

358366
let stderr = ''
359367

0 commit comments

Comments
 (0)