withastro/astro · error · Error

Timeout

Error message

Timeout

What it means

create-astro's tiny execa-like shell() helper spawns child processes (for example npm install during scaffolding) with an optional timeout backed by Node's spawn. If the child is killed by the timeout signal, its exitCode is still null after the close event and the helper reports 'Timeout'. In practice this means the spawned command exceeded its allotted time — usually dependency installation on a slow network or machine.

Solutions

  1. Retry — transient network slowness is the most common cause
  2. Skip install during scaffolding (--no-install) and run npm install manually afterwards without a timeout
  3. If you call shell() yourself, pass a larger opts.timeout (milliseconds)
  4. Make sure the spawned command cannot block on a prompt (pass --yes / CI flags)
Defensive patterns

Strategy: retry

Try / catch

try {
	await shell('npm', ['install', '--no-fund', '--no-audit'], { timeout: 60_000, cwd });
} catch (e) {
	if (e instanceof Error && e.message === 'Timeout') {
		// slow install: retry once with a much larger budget
		await shell('npm', ['install', '--no-fund', '--no-audit'], { timeout: 300_000, cwd });
	} else {
		throw e;
	}
}

Prevention

When it happens

Trigger: shell('npm', ['install'], { timeout }) where the install exceeds the timeout; a spawned command that blocks waiting on stdin (interactive prompt) in a non-TTY environment; extremely slow registries or proxies.

Common situations: npm create astro@latest on slow connections where npm install cannot finish in time; commands prompting for input where no TTY exists; calling shell() directly with a tight timeout.

Understand the failure class

Related errors


AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18). Data as JSON: /api/errors/9751b7fe25c3f6a4. Report an issue: GitHub.

Appendix: source

Thrown at packages/create-astro/src/shell.ts:71

	try {
		const [resolvedCommand, resolvedFlags] = resolveCommand(command, flags);
		child = spawn(resolvedCommand, resolvedFlags, {
			cwd: opts.cwd,
			stdio: opts.stdio,
			timeout: opts.timeout,
		});
		const done = new Promise<void>((resolve, reject) => {
			child.once('error', reject);
			child.once('close', () => resolve());
		});
		[stdout, stderr] = await Promise.all([text(child.stdout), text(child.stderr), done]);
	} catch (e) {
		const message = e instanceof Error ? e.message : stderr || 'Unknown error';
		throw new Error(message);
	}
	const { exitCode } = child;
	if (exitCode === null) {
		throw new Error('Timeout');
	}
	if (exitCode !== 0) {
		throw new Error(stderr || `Process exited with code ${exitCode}`);
	}
	return { stdout, stderr, exitCode };
}

View on GitHub (pinned to 52e6c34790)