withastro/astro · error · Error

Another astro preview server is already running. URL

Error message

Another astro preview server is already running.

  URL:  ${existingServer.url}
  PID:  ${existingServer.pid}

Run `astro preview stop` to stop it, or use `astro preview --force` to replace it.

What it means

`astro preview` reads the preview lock file (`.astro/preview.json` under the project root) and probes the recorded PID before starting. A live preview server is already registered for this root, so the command aborts instead of orphaning `astro preview stop`.

Solutions

  1. Run `astro preview stop` to stop the existing server, then run `astro preview` again
  2. Or replace it: `astro preview --force`
  3. If the recorded PID is dead (or was reused by an unrelated process), delete `.astro/preview.json` in the project root and retry

Example fix

# before
astro preview   # Another astro preview server is already running. URL: ... PID: ...

# after
astro preview stop
astro preview
# or replace directly:
astro preview --force
Defensive patterns

Strategy: validation

Validate before calling

import { existsSync, readFileSync } from 'node:fs';
import { join } from 'node:path';

function previewServerIsRunning(root) {
  const lock = join(root, '.astro', 'preview.json');
  if (!existsSync(lock)) return false;
  try {
    const { pid } = JSON.parse(readFileSync(lock, 'utf8'));
    process.kill(pid, 0);
    return true;
  } catch {
    return false;
  }
}

if (previewServerIsRunning(root)) {
  // run `astro preview stop` (or pass --force) before `astro preview`
}

Try / catch

import { spawnSync } from 'node:child_process';
const r = spawnSync('astro', ['preview'], { encoding: 'utf8' });
if (r.status !== 0 && /Another astro preview server is already running/.test(r.stderr)) {
  spawnSync('astro', ['preview', 'stop'], { stdio: 'inherit' });
  // retry `astro preview` once
}

Prevention

When it happens

Trigger: Running `astro preview` (typically after `astro build`) while another preview server for the same project root is still running — a previous terminal, a detached process, or tooling that started preview earlier.

Common situations: Iterating on production builds and forgetting the previous preview; CI or scripts running preview twice; editor task runners keeping preview alive.

Related errors


AI-assisted analysis of withastro/astro@e294953aa8 (2026-08-18). Data as JSON: /api/errors/98234d2f50872e0f. Report an issue: GitHub.

Appendix: source

Thrown at packages/astro/src/cli/preview/index.ts:146

					'This instance is not tracked by `astro preview stop`, `astro preview status`, or `astro preview logs`.',
				].join('\n'),
			);
		}
		const inlineConfig = flagsToAstroInlineConfig(flags);
		return await previewServer(inlineConfig);
	}

	const existingServer = await checkExistingServer(root, 'preview');
	if (existingServer) {
		const message = [
			'Another astro preview server is already running.',
			'',
			`  URL:  ${existingServer.url}`,
			`  PID:  ${existingServer.pid}`,
			'',
			`Run \`astro preview stop\` to stop it, or use \`astro preview --force\` to replace it.`,
		].join('\n');
		throw new Error(message);
	}

	const inlineConfig = flagsToAstroInlineConfig(flags);
	const server = await previewServer(inlineConfig);
	const serverUrl = server.urls?.local[0]
		? new URL(server.urls.local[0]).origin
		: `http://${server.host ?? 'localhost'}:${server.port}`;

	writeLockFile(
		root,
		{
			pid: process.pid,
			port: server.port,
			url: serverUrl,
			urls: server.urls,
			background: !!process.env.ASTRO_PREVIEW_BACKGROUND,
			startedAt: new Date().toISOString(),
		},

View on GitHub (pinned to e294953aa8)