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

  1. Read `result.message` / catch the error to see execa's detailed reason (ENOENT, EACCES, etc.)
  2. Verify the command exists: `which <cmd>` or use an absolute path to the binary
  3. Ensure `cwd` exists and is accessible before spawning
  4. 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

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


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/b9b9129fb554e4e5. Report an issue: GitHub.