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` uses the same lock-file mechanism as `astro dev` but keyed to the `'preview'` role. Before binding it checks `checkExistingServer(root, 'preview')` and refuses to start a second preview server against the same project root. `--force` is supported to kill and replace the prior preview process.
Source
Thrown at packages/astro/src/cli/preview/index.ts:93
logger.error(
'SKIP_FORMAT',
`Unknown command: astro preview ${subcommand}\n\nRun \`astro preview --help\` to see available commands.`,
);
process.exit(1);
}
const root = pathToFileURL(resolveRoot(flags.root) + '/');
const existingServer = 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 d081033d5f)
Solutions
- Run `astro preview stop` to stop the existing preview server.
- Run `astro preview --force` to replace it in one command.
- Manually kill the recorded PID and remove the preview lock file in `.astro/` if the process is already dead but the lock is stale.
- Verify with `ps -p <PID>` before killing anything.
Example fix
// before $ astro preview // after $ astro preview --force
Defensive patterns
Strategy: validation
Validate before calling
function isPreviewServerRunning(root) {
const lockPath = join(root, '.astro', 'preview.lock');
if (!existsSync(lockPath)) return null;
try {
const { pid, url } = JSON.parse(readFileSync(lockPath, 'utf-8'));
if (pid && process.kill(pid, 0)) return { pid, url };
} catch {}
return null;
} Prevention
- Stop preview servers with `astro preview stop` before restarting.
- Use `astro preview --force` in automated build/preview pipelines.
When it happens
Trigger: Running `astro preview` while a prior `astro preview` for the same root still holds the lock (live PID). Distinct from the dev server lock — a running `astro dev` does not trigger this, only another preview does.
Common situations: A preview server left running after building and starting it in another terminal; CI caching a workspace with a stale preview process; switching between multiple builds and forgetting the previous preview is still serving the old `dist/`.
Related errors
- Another astro dev server is already running. URL: ${exis
- Unknown error parsing tsconfig.json or jsconfig.json. Could
- ${integration} does not appear to be a valid package name!
- No problem! Find our official integrations at https://astro.
- Unable to fetch ${integration}. Does the package exist?
AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12).
Data as JSON: /api/errors/98234d2f50872e0f.
Report an issue: GitHub.