{"id":"ad0a0ccd8a3f2031","repo":"vitest-dev/vitest","slug":"cannot-spawn-child-server-without-a-parent-dev-ser","errorCode":null,"errorMessage":"Cannot spawn child server without a parent dev server.","messagePattern":"Cannot spawn child server without a parent dev server\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/browser/src/node/projectParent.ts","lineNumber":158,"sourceCode":"      resolve(distRoot, 'client/esm-client-injector.js'),\n      'utf8',\n    ).then(js => (this.injectorJs = js))\n    this.errorCatcherUrl = join('/@fs/', resolve(distRoot, 'client/error-catcher.js'))\n\n    this.matchersUrl = join('/@fs/', distRoot, 'expect-element.js')\n    this.stateJs = readFile(\n      resolve(distRoot, 'state.js'),\n      'utf-8',\n    ).then(js => (this.stateJs = js))\n  }\n\n  public setServer(vite: Vite.ViteDevServer): void {\n    this.vite = vite\n  }\n\n  public spawn(project: TestProject): ProjectBrowser {\n    if (!this.vite) {\n      throw new Error(`Cannot spawn child server without a parent dev server.`)\n    }\n    const clone = new ProjectBrowser(\n      this,\n      project,\n      '/',\n    )\n    this.children.add(clone)\n    return clone\n  }\n\n  public parseErrorStacktrace(\n    e: TestError,\n    options: StackTraceParserOptions = {},\n  ): ParsedStack[] {\n    return parseErrorStacktrace(e, {\n      ...this.stackTraceOptions,\n      ...options,\n    })","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/browser/src/node/projectParent.ts#L140-L176","documentation":"`ParentBrowserProject.spawn` creates a `ProjectBrowser` and copies `this.vite` into it. The check `if (!this.vite)` rejects the spawn when the parent's Vite dev server was never assigned via `setServer`, preventing a child from running without the shared dev server it depends on.","triggerScenarios":"Calling `parent.spawn(project)` before `parent.setServer(vite)` was invoked — an internal lifecycle violation.","commonSituations":"Internal Vitest bug or a custom orchestration layer that constructs `ParentBrowserProject` and calls `spawn` manually without first wiring the dev server. Standard Vitest runs always call `setServer` during plugin setup.","solutions":["If you're calling `spawn` directly, call `parent.setServer(vite)` first.","If this fires during a normal `vitest` run, update Vitest and `@vitest/browser` to matching versions and report the issue with a reproduction.","Check that the browser plugin was registered (e.g. not disabled via config)."],"exampleFix":"// before\nconst parent = new ParentBrowserProject({ config, vitest }, '/')\nparent.spawn(project)\n\n// after\nparent.setServer(viteDevServer)\nparent.spawn(project)","handlingStrategy":"validation","validationCode":"function assertParentReady(parent: { vite?: unknown }): void {\n  if (!parent.vite) {\n    throw new Error('Call parent.setServer(vite) before parent.spawn(project)')\n  }\n}","typeGuard":"const parentHasServer = (p: { vite?: unknown }): p is { vite: object } => !!p.vite","tryCatchPattern":null,"preventionTips":["Don't call spawn() directly; let Vitest's plugin lifecycle manage it.","If writing a custom integration, call setServer(vite) before spawn.","Report occurrences during normal vitest runs as a bug."],"tags":["lifecycle","browser","internal","bug"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}