{"record":{"id":"16a77847df0d4332","repo":"denoland/deno","slug":"v8-startupsnapshot-setdeserializemainfunction-ca","errorCode":null,"errorMessage":"v8.startupSnapshot.setDeserializeMainFunction() can only be called once.","messagePattern":"v8\\.startupSnapshot\\.setDeserializeMainFunction\\(\\) can only be called once\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/v8.ts","lineNumber":588,"sourceCode":"// is an API-surface polyfill that lets modules calling `v8.startupSnapshot`\n// load without errors. `isBuildingSnapshot()` always returns false. The\n// serialize/deserialize callbacks are stored but never invoked because there\n// is no snapshot lifecycle. `setDeserializeMainFunction` invokes the callback\n// synchronously so scripts that register a deserialize main still run their\n// entry point in plain Deno runs.\n// deno-lint-ignore no-explicit-any\ntype SnapshotCallback = (data: any) => unknown;\nconst serializeCallbacks: { fn: SnapshotCallback; data: unknown }[] = [];\nconst deserializeCallbacks: { fn: SnapshotCallback; data: unknown }[] = [];\nlet deserializeMainCalled = false;\n\nfunction startupSnapshotSetDeserializeMainFunction(\n  fn: SnapshotCallback,\n  data?: unknown,\n) {\n  validateFunction(fn, \"callback\");\n  if (deserializeMainCalled) {\n    throw new Error(\n      \"v8.startupSnapshot.setDeserializeMainFunction() can only be called once.\",\n    );\n  }\n  deserializeMainCalled = true;\n  fn(data);\n}\n\nfunction startupSnapshotAddSerializeCallback(\n  fn: SnapshotCallback,\n  data?: unknown,\n) {\n  validateFunction(fn, \"callback\");\n  ArrayPrototypePush(serializeCallbacks, { fn, data });\n}\n\nfunction startupSnapshotAddDeserializeCallback(\n  fn: SnapshotCallback,\n  data?: unknown,","sourceCodeStart":570,"sourceCodeEnd":606,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/v8.ts#L570-L606","documentation":"v8.startupSnapshot.setDeserializeMainFunction(fn, data) registers the single main callback that runs when a startup snapshot is deserialized; the API contract allows exactly one. The polyfill tracks a module-level deserializeMainCalled flag and throws a plain Error on any second call, matching Node.","triggerScenarios":"Calling setDeserializeMainFunction twice in the same isolate — module top-level registration re-executed during dev reload/HMR, or two modules both trying to own the snapshot entry point.","commonSituations":"Snapshot-building scripts refactored so registration moved into a shared helper invoked from two files; test harnesses importing the snapshot script twice; boilerplate duplicated between entry points.","solutions":["Register the main function in exactly one module and delete the duplicate call.","For repeatable setup use addSerializeCallback/addDeserializeCallback, which accept multiple registrations.","Guard registration behind a module-level flag when re-execution is possible (HMR, tests)."],"exampleFix":"// before — two entrypoints each register a main\nstartupSnapshot.setDeserializeMainFunction(mainA);\nstartupSnapshot.setDeserializeMainFunction(mainB); // Error: can only be called once\n\n// after — one main that dispatches, plus callbacks for the rest\nstartupSnapshot.setDeserializeMainFunction(mainA);\nstartupSnapshot.addDeserializeCallback(() => mainB());","handlingStrategy":"validation","validationCode":"let mainRegistered = false;\nexport function registerSnapshotMain(fn, data) {\n  if (mainRegistered) return; // idempotent across HMR/test re-imports\n  mainRegistered = true;\n  v8.startupSnapshot.setDeserializeMainFunction(fn, data);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep snapshot entry registration in a single dedicated file.","Prefer addDeserializeCallback for anything additive or optional.","Note Deno's polyfill reports isBuildingSnapshot() === false — registration here is bookkeeping, so design entry logic accordingly."],"tags":["v8","startup-snapshot","double-call","initialization"],"backgroundTag":"double-initialization","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}