{"record":{"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":"critical","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/1fa9837ec26533512fdcad8baebf249771bd340a/packages/browser/src/node/projectParent.ts#L140-L176","documentation":"ProjectParentBrowser.spawn clones itself into a child ProjectBrowser tied to a TestProject, and the clone needs the parent's Vite dev server (this.vite) to resolve modules. setServer() is what assigns that server; if spawn() is called before setServer(), there is nothing to clone from and the error fires.","triggerScenarios":"Calling projectParent.spawn(project) before the parent's setServer(viteDevServer) hook has run. Typically an internal ordering bug in the browser plugin lifecycle, or a custom integration that drives spawn manually.","commonSituations":"A plugin that constructs a TestProject and calls spawn() during configureServer before the parent server reference is stored; a regression in plugin ordering after upgrading Vite/Vitest; a test harness that mocks parts of the lifecycle.","solutions":["If you are a plugin author, defer spawn() to a server-ready hook (e.g. after configureServer resolves) so setServer has run.","Ensure no code path constructs a TestProject and immediately spawns its browser before the parent server is registered.","On stock Vitest, upgrade to a version where plugin ordering is correct and report a bug with a reproduction if it persists."],"exampleFix":"// before\nconst child = parent.spawn(project) // parent.vite not yet set\n// after\nparent.setServer(viteDevServer)\nconst child = parent.spawn(project)","handlingStrategy":"validation","validationCode":"function parentServerReady(parent: { vite?: unknown }): boolean {\n  return !!parent.vite\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Plugin authors: call spawn() only from a hook that fires after setServer().","Never construct a TestProject and immediately spawn its browser in configureServer.","Keep a regression test that exercises the full plugin lifecycle ordering."],"tags":["lifecycle","browser","vite-server","internal-invariant","ordering"],"backgroundTag":null,"analyzedSha":"1fa9837ec26533512fdcad8baebf249771bd340a","analyzedAt":"2026-08-11T16:11:39.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}