windmill-labs/windmill · warning
Could not open in Claude Desktop: ${errorMessage}
Error message
Could not open in Claude Desktop: ${errorMessage} What it means
Warning from `wmill app new`'s outer catch around the whole 'Open in Claude Desktop' block. It fires when any awaited step before the deep-link exec fails: writing/seeding .claude/launch.json (mkdir/stat/writeFile errors), or spawning `claude --session-id <uuid> -p ...` to create the session (exec rejection). The CLI prints the error message and tells the user to manually run `cd <folder> && claude`.
Source
Thrown at cli/src/commands/app/new.ts:876
// the deep link doesn't pass through a shell — `sessionId` is a UUID
// and absAppDir is URI-encoded inside the URL today, but execFile
// removes shell escaping concerns entirely.
const deepLink = `claude://resume?session=${sessionId}&cwd=${encodeURIComponent(absAppDir)}`;
execFile("open", [deepLink], (err) => {
if (err) {
log.warn(
colors.yellow(
`Could not open Claude Desktop deep link (${err.message}). Open it manually: ${deepLink}`
)
);
} else {
log.info(colors.bold.green("Opened in Claude Desktop!"));
}
});
} catch (error: unknown) {
const errorMessage =
error instanceof Error ? error.message : String(error);
log.warn(
colors.yellow(
`Could not open in Claude Desktop: ${errorMessage}`
)
);
log.info(
colors.gray(
"You can manually run: cd " + folderName + " && claude"
)
);
}
}
}
}
const command = new Command()
.description("create a new raw app from a template")
.option(
"--summary <summary:string>",View on GitHub (pinned to e474e8803c)
Solutions
- Check that the `claude` CLI is installed and works: run `claude --version` and `claude -p 'hi'` in the app folder; install/update Claude Code if missing.
- Run the manual fallback the CLI prints: `cd <appFolder> && claude`, then start the preview with `wmill app dev`.
- Check filesystem permissions on the new app directory; ensure .claude/launch.json can be created (or create it manually).
- If the error came from the claude command itself, read its message (auth/login errors) and run `claude /login` or fix the API key, then retry `wmill app new`.
- Use --open-in-desktop=false (or answer No at the prompt) to skip this optional step entirely; app scaffolding is unaffected.
Example fix
// before: failing inside the block
await writeFile(launchPath, launchJson, "utf-8");
// after: caller-side guard before running app new
const claudeBin = which.sync("claude", { nothrow: true });
if (!claudeBin) {
console.log('claude CLI not found; skipping desktop open (run `cd dir && claude` later).');
} Defensive patterns
Strategy: try-catch
Validate before calling
import { which } from "@cliffy/command"; // or check PATH manually
const claudeOnPath = !!await new Promise<boolean>((res) =>
execFile("claude", ["--version"], (err) => res(!err)));
if (!claudeOnPath) console.warn('claude CLI missing; desktop-open step will fail.'); Type guard
function isNodeSystemError(e: unknown): e is NodeJS.ErrnoException {
return e instanceof Error && typeof (e as NodeJS.ErrnoException).code === "string";
} Try / catch
try {
await seedLaunchJson(absAppDir);
await createClaudeSession(absAppDir);
openDeepLink(sessionId, absAppDir);
} catch (error) {
const msg = error instanceof Error ? error.message : String(error);
log.warn(`Could not open in Claude Desktop: ${msg}`);
log.info(`Fallback: cd ${folderName} && claude`);
} Prevention
- Install and authenticate the Claude Code CLI (`claude --version`, `claude /login`) before using the desktop-open feature.
- Ensure the target app directory is writable so .claude/launch.json seeding succeeds.
- Pass --open-in-desktop=false in scripts/CI to skip this optional, environment-dependent step entirely.
- Keep Claude Code and Claude Desktop versions in sync to avoid session-creation failures.
When it happens
Trigger: `wmill app new` reached the desktop-open step and either (a) the filesystem rejects the launch.json seeding (read-only dir, permission denied on mkdir/writeFile), or (b) the spawned `claude` CLI binary exits non-zero or cannot be spawned (claude not on PATH, command failed), rejecting the wrapped exec promise.
Common situations: Claude Code CLI (`claude`) not installed or not on PATH while Claude Desktop is; corrupted npm/bun global install of claude-code; app directory created on a read-only mount; .claude/launch.json exists with restrictive permissions; claude CLI failing auth on first run.
Related errors
- File not found: ${filePath}
- Workspace folder not found, are you in the right directory?
- Directory not found: ${targetDirectory}
- Path is not a directory: ${targetDirectory}
- file path must refer to a file.
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/58dcf1d99795dd34.
Report an issue: GitHub.