mastra-ai/mastra · critical
Process failed to spawn
Error message
Process failed to spawn
What it means
LocalProcessManager.spawn() throws when execa could not start the process — `subprocess.pid` is undefined because the spawn failed synchronously (bad cwd, missing executable, permission issues). The manager awaits the subprocess promise to pull execa's detailed error message and throws that, or a generic fallback.
Source
Thrown at packages/core/src/workspace/sandbox/local-process-manager.ts:278
// Non-isolated: use shell mode so the host shell interprets the command string
// (pipes, redirects, chaining, etc.). Isolated (seatbelt/bwrap): the wrapper
// already includes `sh -c` inside the sandbox, so we spawn the wrapper directly.
execaOptions = {
...baseOptions,
detached: true,
shell: this.sandbox.isolation === 'none',
};
}
const execa = await getExeca();
const subprocess = execa(wrapped.command, wrapped.args, execaOptions);
// execa sets pid synchronously when the process spawns successfully.
// If pid is undefined, the spawn failed (bad cwd, missing command, etc.).
// Await the subprocess to get execa's detailed error message.
if (!subprocess.pid) {
const result = await subprocess;
throw new Error(result.message || 'Process failed to spawn');
}
const handle = new LocalProcessHandle(subprocess, subprocess.pid, Date.now(), options);
this._tracked.set(handle.pid, handle);
return handle;
}
async list(): Promise<ProcessInfo[]> {
return Array.from(this._tracked.values()).map(handle => ({
pid: handle.pid,
running: handle.exitCode === undefined,
exitCode: handle.exitCode,
}));
}
}
View on GitHub (pinned to 75dd419e61)
Solutions
- Read `result.message` / catch the error to see execa's detailed reason (ENOENT, EACCES, etc.)
- Verify the command exists: `which <cmd>` or use an absolute path to the binary
- Ensure `cwd` exists and is accessible before spawning
- Check execute permissions on the target binary (chmod +x)
Example fix
// before
const handle = await manager.spawn({ cmd: 'mytool' });
// after
const bin = path.join(projectRoot, 'node_modules/.bin/mytool');
if (!fs.existsSync(bin)) throw new Error(`mytool not installed at ${bin}`);
const handle = await manager.spawn({ cmd: bin, options: { cwd: projectRoot } }); Defensive patterns
Strategy: try-catch
Validate before calling
import fs from 'fs';
function assertSpawnable(cmd: string, cwd?: string) {
if (cwd && !fs.existsSync(cwd)) throw new Error(`cwd does not exist: ${cwd}`);
if (cmd.includes('/')) fs.accessSync(cmd, fs.constants.X_OK);
} Try / catch
try {
const handle = await manager.spawn({ cmd, options: { cwd } });
} catch (err) {
if (/failed to spawn|ENOENT|EACCES/.test(String(err?.message))) {
throw new Error(`Cannot start '${cmd}' in '${cwd}': ${err.message}. Check the binary exists and is executable.`);
}
throw err;
} Prevention
- Use absolute binary paths (e.g. node_modules/.bin/*) instead of relying on PATH
- Verify cwd exists before spawning; resolve relative paths against a known root
- Include the failing command and cwd in your own error messages for debuggability
When it happens
Trigger: Calling `spawn()` with a command that doesn't exist on PATH, a `cwd` directory that doesn't exist, or a binary without execute permission. Any case where the child fails to start so execa never assigns a pid.
Common situations: Typo'd or platform-specific command names (e.g. `dir` on unix); missing system dependencies in sandbox/container images; relative cwd paths that don't resolve; trying to run node_modules/.bin tools before install.
Related errors
- execa is not available in Cloudflare Workers
- Sandbox provider "${sandbox.provider}" does not support netw
- Sandbox provider "${sandbox.provider}" did not expose a publ
- Woke sandbox but the Mastra server did not become healthy at
- createSandboxProxy requires an Edge Config connection string
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/b9b9129fb554e4e5.
Report an issue: GitHub.