{"record":{"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":"error","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/1fa9837ec26533512fdcad8baebf249771bd340a/packages/vitest/src/api/setup.ts#L58-L94","documentation":"The Vitest WebSocket API exposes saveTestFile(id, content) for tools (like the VS Code extension or UI) to write test file contents. It checks that the id is both registered in ctx.state.filesMap and exists on disk. If either fails, the file was never collected/registered by Vitest, so the API refuses to write it.","triggerScenarios":"A client calls saveTestFile with a file path that Vitest has not collected (not in the current test glob) or that doesn't exist on disk; calling the RPC method before Vitest has finished its initial collection.","commonSituations":"Editor extension trying to save a file outside the configured test.include; race condition where save is attempted before collection completes; stale id after a file was renamed/deleted.","solutions":["Ensure the file id matches a path that Vitest has actually collected (check getFiles/getPaths from the same API).","Wait for Vitest's collection to finish before issuing saveTestFile.","If the file was renamed/moved, update the client to use the new registered path."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// before calling saveTestFile via RPC:\nconst files = await rpc.getFiles()\nif (!files.some(f => f.id === targetId)) {\n  // file not registered; skip the save\n}","typeGuard":null,"tryCatchPattern":"try {\n  await api.saveTestFile(id, content)\n} catch (e) {\n  if (e.message.includes('was not registered')) {\n    // refresh file list and retry, or notify user\n  } else throw e\n}","preventionTips":["Always verify a file id is in getFiles() before calling saveTestFile.","Refresh the file list after rename/delete operations before saving."],"tags":["api","websocket","editor-integration","file-registration"],"backgroundTag":null,"analyzedSha":"1fa9837ec26533512fdcad8baebf249771bd340a","analyzedAt":"2026-08-11T16:11:39.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}