angular/angular-cli · error · Error

Port ${input.port} is unavailable. Try calling this tool aga

Error message

Port ${input.port} is unavailable. Try calling this tool again without the 'port' parameter to auto-assign a free port.

What it means

The devserver_start tool checks the requested port via context.host.isPortAvailable before binding. If the port is already in use (or otherwise unavailable), it throws and suggests omitting the port parameter so the tool auto-assigns a free one.

Source

Thrown at packages/angular/cli/src/commands/mcp/tools/devserver/devserver-start.ts:67

    workspacePathInput: input.workspace,
    projectNameInput: input.project,
    mcpWorkspace: context.workspace,
  });

  const key = getDevserverKey(workspacePath, projectName);

  let devserver = context.devservers.get(key);
  if (devserver) {
    return createStructuredContentOutput({
      message: `Development server for project '${projectName}' is already running.`,
      address: localhostAddress(devserver.port),
    });
  }

  let port: number;
  if (input.port) {
    if (!(await context.host.isPortAvailable(input.port))) {
      throw new Error(
        `Port ${input.port} is unavailable. Try calling this tool again without the 'port' parameter to auto-assign a free port.`,
      );
    }
    port = input.port;
  } else {
    port = await context.host.getAvailablePort();
  }

  devserver = new LocalDevserver({
    host: context.host,
    project: projectName,
    port,
    workspacePath,
  });
  devserver.start();

  context.devservers.set(key, devserver);

View on GitHub (pinned to bb72145f9a)

Solutions

  1. Call the tool again without the 'port' parameter so a free port is auto-assigned.
  2. Stop the process occupying the port (lsof -i :<port> / netstat to identify it, then kill it).
  3. Choose a different, higher, unprivileged port (e.g. 49152+).
  4. Shut down previously started dev servers via the devserver stop tool before restarting.

Example fix

// before
devserver_start({ port: 4200 });
// after
devserver_start({}); // port auto-assigned
Defensive patterns

Strategy: retry

Validate before calling

import { createServer } from 'node:net';
function isPortFree(port: number): Promise<boolean> {
  return new Promise((res) => {
    const srv = createServer();
    srv.once('error', () => res(false));
    srv.once('listening', () => srv.close(() => res(true)));
    srv.listen(port);
  });
}
if (!(await isPortFree(4200))) console.warn('port 4200 busy — omit port param');

Try / catch

try {
  await devserver_start({ port: 4200 });
} catch (e) {
  if ((e as Error).message.includes('is unavailable')) {
    await devserver_start({}); // auto-assign free port
  } else throw e;
}

Prevention

When it happens

Trigger: Calling devserver_start with input.port set to a port already occupied by another process, or a port below 1024 without privileges, or raced by another service binding between check and bind.

Common situations: A previous dev server still running on 4200; another app (Docker, other dev server) holding the port; re-running the tool after a previous session that didn't shut down; reusing a hardcoded port across projects.

Related errors


AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30). Data as JSON: /api/errors/0093cd0f232e670b. Report an issue: GitHub.