windmill-labs/windmill · warning
Could not open Claude Desktop deep link (${err.message}). Op
Error message
Could not open Claude Desktop deep link (${err.message}). Open it manually: ${deepLink} What it means
Warning emitted by `wmill app new` after scaffolding, when it tries to resume/import the freshly created Claude session in Claude Desktop via the macOS `open` command with a claude:// deep link. The execFile('open', [deepLink]) callback received an error, meaning macOS failed to hand the URL to the Claude Desktop app (e.g. `open` binary missing/failed or no app registered for the claude:// scheme). The CLI suggests opening the printed deep link manually and continues.
Source
Thrown at cli/src/commands/app/new.ts:864
{ cwd: absAppDir },
(error) => (error ? reject(error) : resolve())
);
});
} finally {
// On exec rejection control jumps to the outer catch — without this
// finally the spinner keeps writing to stdout and garbles output.
clearInterval(spinner);
process.stdout.write("\r" + " ".repeat(40) + "\r");
}
// Import the session into Claude Desktop Code mode. Use execFile so
// 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(View on GitHub (pinned to e474e8803c)
Solutions
- Open the printed deep link manually (copy `claude://resume?session=...&cwd=...` into a browser or Spotlight) to resume the session in Claude Desktop.
- Verify Claude Desktop is installed and launched at least once so it registers the claude:// scheme, then retry `wmill app new`.
- Test the handler manually: run `open 'claude://resume'` in a terminal; if it fails, re-install or re-launch Claude Desktop.
- As a fallback, run `cd <appDir> && claude` in the terminal, which the CLI also suggests on the sibling error path.
Example fix
// before (inside the CLI's callback path)
execFile("open", [deepLink], (err) => { if (err) log.warn(...); });
// after (caller-side manual fallback)
execFile("open", [deepLink], (err) => {
if (err) {
console.log(`Open manually: ${deepLink}`);
// or: execFile("xdg-open", [deepLink]) on Linux
}
}); Defensive patterns
Strategy: try-catch
Validate before calling
import { execFile } from "node:child_process";
function canOpenDeepLinks(): Promise<boolean> {
return new Promise((res) =>
execFile("open", ["-Ra", "Claude"], (err) => res(!err))
);
} Type guard
function isExecFileError(e: NodeJS.ErrnoException | null): e is NodeJS.ErrnoException & { code: string } {
return e !== null && typeof e.code === "string";
} Try / catch
execFile("open", [deepLink], (err) => {
if (err) {
log.warn(`Deep link failed (${err.message}); open manually: ${deepLink}`);
} else {
log.info("Opened in Claude Desktop!");
}
}); Prevention
- Launch Claude Desktop once after install/update so it re-registers the claude:// URL scheme.
- Test `open 'claude://resume'` manually before scripting the desktop-open flow.
- On Linux/Windows use the platform opener (xdg-open / `start`) instead of macOS `open`.
- Avoid running the desktop-open step over SSH or headless sessions where no GUI handler exists.
When it happens
Trigger: Running `wmill app new` on macOS with Claude Desktop detected, answering 'Open in Claude Desktop?', and execFile('open', [deepLink]) invokes its callback with an error: `open` not found or non-zero exit (no handler registered for claude://, Claude Desktop uninstalled/deregistered, or headless environment without a GUI session).
Common situations: Claude Desktop installed but its URL handler deregistered after an update; running over SSH without a GUI login session; macOS security prompts blocking `open`; user on Linux where /usr/bin/open is not macOS's open (e.g. openstructure) and cannot handle claude://.
Related errors
- Could not open in Claude Desktop: ${errorMessage}
- App ${appPath} not found
- Dependency generation failed: ${queueResponse.status} ${queu
- Failed to poll dependencies job ${jobId}: ${e?.message ?? e}
- No response body for SSE stream
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/712ccf9746760eb9.
Report an issue: GitHub.