{"record":{"id":"28f2516508f7fdeb","repo":"heygen-com/hyperframes","slug":"multiple-studio-preview-servers-match-this-project","errorCode":null,"errorMessage":"Multiple Studio preview servers match this project (${ports.join(\", \")}). Pass --port <port> to choose one.","messagePattern":"Multiple Studio preview servers match this project \\((.+?)\\)\\. Pass --port <port> to choose one\\.","errorType":"exception","errorClass":"AmbiguousPreviewServerError","httpStatus":null,"severity":"error","filePath":"packages/cli/src/utils/studioSelectionClient.ts","lineNumber":87,"sourceCode":"  const normalizedProjectDir = normalizePath(projectDir);\n  const servers = await scan(startPort);\n  const embeddedServers = servers.filter(\n    (server) => normalizePath(server.projectDir) === normalizedProjectDir,\n  );\n  if (options.preferredPort !== undefined) {\n    const preferred = embeddedServers.find((server) => server.port === options.preferredPort);\n    if (preferred) return preferred;\n    const viteServer = await findViteStudioServerForProject(normalizedProjectDir, fetchImpl, [\n      options.preferredPort,\n    ]);\n    if (viteServer) return viteServer;\n    if (embeddedServers.length > 0) {\n      throw new PreviewServerPortMismatchError(options.preferredPort, embeddedServers);\n    }\n    return null;\n  }\n  if (embeddedServers.length === 1) return embeddedServers[0]!;\n  if (embeddedServers.length > 1) throw new AmbiguousPreviewServerError(embeddedServers);\n  return findViteStudioServerForProject(normalizedProjectDir, fetchImpl);\n}\n\nexport function studioSelectionUrl(server: ActiveServer): string {\n  return studioApiUrl(server, \"selection\");\n}\n\nexport function studioApiUrl(server: ActiveServer, route: string): string {\n  const host = server.host ?? \"127.0.0.1\";\n  return `http://${host}:${server.port}/api/projects/${encodeURIComponent(server.projectName)}/${route}`;\n}\n\n// Vite dev servers bind IPv6 loopback (`::1`) by default while embedded servers\n// bind IPv4 (`127.0.0.1`), so probe both — a single family misses the other and\n// is exactly why `--selection`/`--context` failed against a local-studio preview.\nconst LOOPBACK_HOSTS = [\"127.0.0.1\", \"[::1]\"] as const;\n\nasync function findViteStudioServerForProject(","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/utils/studioSelectionClient.ts#L69-L105","documentation":"Thrown as AmbiguousPreviewServerError when more than one embedded Studio preview server matches the project directory and no --port was specified. The CLI cannot safely auto-select one, so it lists the matching ports and asks the user to disambiguate with --port.","triggerScenarios":"Two or more Studio preview server processes are running for the same project directory on different ports (e.g. the user started preview twice, or a previous instance didn't shut down). Without --port, the CLI finds multiple embeddedServers and throws.","commonSituations":"Starting a second preview without killing the first; a zombie Studio process from a crashed session; running preview in two terminal windows for the same project.","solutions":["Pass --port with one of the ports listed in the error to choose which server to use.","Kill the stale preview server process (check with tman list or ps) and retry without --port.","If both servers are intentional, always specify --port to disambiguate."],"exampleFix":"// before: hyperframes lint   (multiple servers found)\n// after:  hyperframes lint --port 3002","handlingStrategy":"validation","validationCode":"import { scanActiveServers } from \"../server/portUtils.js\";\n\nasync function checkForDuplicateServers(projectDir: string): Promise<number[]> {\n  const servers = (await scanActiveServers()).filter(\n    (s) => normalizePath(s.projectDir) === normalizePath(projectDir),\n  );\n  return servers.map((s) => s.port);\n}","typeGuard":"function isAmbiguousPreviewServer(err: unknown): err is AmbiguousPreviewServerError {\n  return err instanceof AmbiguousPreviewServerError;\n}","tryCatchPattern":"try {\n  const server = await findPreviewServerForProject(dir);\n} catch (err) {\n  if (err instanceof AmbiguousPreviewServerError) {\n    console.error(`Multiple servers on ports: ${err.ports.join(\", \")}. Pass --port to choose.`);\n    process.exit(1);\n  }\n  throw err;\n}","preventionTips":["Kill stale preview servers before starting new ones to avoid duplicates.","Always specify --port when running multiple preview servers for the same project.","Use tman list or ps to check for lingering server processes."],"tags":["studio","preview-server","port","cli"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}