{"id":"099fd92676e66cd9","repo":"vitest-dev/vitest","slug":"test-file-id-was-not-registered-so-it-cannot","errorCode":null,"errorMessage":"Test file \"${id}\" was not registered, so it cannot be updated using the API.","messagePattern":"Test file \"(.+?)\" was not registered, so it cannot be updated using the API\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/vitest/src/api/setup.ts","lineNumber":76,"sourceCode":"\n  function setupClient(ws: WebSocket) {\n    const rpc = createBirpc<WebSocketEvents, WebSocketHandlers>(\n      {\n        getFiles() {\n          return ctx.state.getFiles()\n        },\n        getPaths() {\n          return ctx.state.getPaths()\n        },\n        async readTestFile(id) {\n          if (!ctx.state.filesMap.has(id) || !existsSync(id)) {\n            return null\n          }\n          return fs.readFile(id, 'utf-8')\n        },\n        async saveTestFile(id, content) {\n          if (!ctx.state.filesMap.has(id) || !existsSync(id)) {\n            throw new Error(\n              `Test file \"${id}\" was not registered, so it cannot be updated using the API.`,\n            )\n          }\n          // silently ignore write attempts if not allowed\n          if (!ctx.config.api.allowWrite) {\n            return\n          }\n          return fs.writeFile(id, content, 'utf-8')\n        },\n        async rerun(files, resetTestNamePattern) {\n          // silently ignore exec attempts if not allowed\n          if (!ctx.config.api.allowExec) {\n            return\n          }\n          await ctx.rerunFiles(files, undefined, true, resetTestNamePattern)\n        },\n        async rerunTask(id) {\n          // silently ignore exec attempts if not allowed","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/vitest/src/api/setup.ts#L58-L94","documentation":"Thrown by the saveTestFile RPC handler in packages/vitest/src/api/setup.ts when the WebSocket API client (typically the Vitest UI or an editor integration) requests a saveTestFile for an id that is neither in ctx.state.filesMap nor present on disk. The save is refused to avoid creating phantom files or overwriting unrelated paths through the API surface.","triggerScenarios":"The UI sends a save request for a file that hasn't been collected in this run (e.g. a newly created test file not yet picked up by the watcher); the file was deleted between collection and the save request; an external tool calling the RPC with a stale id.","commonSituations":"Editor saves a brand-new test file before Vitest re-collects; watcher missed an add event; race between file creation, save, and glob re-scan; the API is being driven against a Vitest server that doesn't have that file in its project root.","solutions":["Save the file once on disk first, then trigger a Vitest re-run/re-collection so filesMap picks it up.","Ensure the file matches test.include and lives under the project root Vitest was started with.","If using the UI, refresh the file list so the new spec is collected before editing through the API.","Confirm the WebSocket client is talking to the same Vitest instance that collected the tests (no stale reconnect)."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function isRegisteredTestFile(id: string, filesMap: Map<string, unknown>): boolean {\n  return filesMap.has(id)\n}","typeGuard":null,"tryCatchPattern":"try {\n  await rpc.saveTestFile(id, content)\n} catch (err) {\n  if (err.message.includes('was not registered')) {\n    // trigger re-collection then retry\n  } else throw err\n}","preventionTips":["Persist new test files on disk before invoking the save API.","Refresh/re-collect in the UI before editing a freshly added spec through the API.","Ensure the file matches test.include and lives under the project root."],"tags":["api","websocket","ui","file-registration"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}