{"record":{"id":"ec20fca2685ef67f","repo":"pydantic/monty","slug":"monty-wasm-component-requested-process-exit","errorCode":null,"errorMessage":"Monty wasm component requested process exit","messagePattern":"Monty wasm component requested process exit","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"crates/monty-js/ts/worker/host.ts","lineNumber":70,"sourceCode":"      exit: denyProcessExit,\n      exitWithCode: denyProcessExit,\n    },\n    'wasi:cli/stderr': imports['wasi:cli/stderr'],\n    'wasi:cli/stdin': imports['wasi:cli/stdin'],\n    'wasi:cli/stdout': imports['wasi:cli/stdout'],\n    'wasi:clocks/monotonic-clock': imports['wasi:clocks/monotonic-clock'],\n    'wasi:clocks/wall-clock': imports['wasi:clocks/wall-clock'],\n    'wasi:filesystem/preopens': imports['wasi:filesystem/preopens'],\n    'wasi:filesystem/types': imports['wasi:filesystem/types'],\n    'wasi:io/error': imports['wasi:io/error'],\n    'wasi:io/streams': imports['wasi:io/streams'],\n    'wasi:random/random': imports['wasi:random/random'],\n  }\n}\n\n/** Turns a guest exit into a component failure instead of terminating Node. */\nfunction denyProcessExit(): never {\n  throw new Error('Monty wasm component requested process exit')\n}\n\n/** Resolves Jco's relative core-module path against the precompiled module map. */\nfunction getModule(modules: ComponentModules, path: string): WebAssembly.Module {\n  const module = modules[path] ?? modules[path.replace(/^\\.\\//, '')]\n  if (!module) throw new Error(`component core module is missing: ${path}`)\n  return module\n}\n","sourceCodeStart":52,"sourceCodeEnd":79,"githubUrl":"https://github.com/pydantic/monty/blob/adc986b362e3961f407868cb118a99fe831b9e61/crates/monty-js/ts/worker/host.ts#L52-L79","documentation":"The WASI component running the Monty worker called `process.exit` (e.g. via an OOM path or guest-requested exit). Instead of letting that terminate the whole Node process, denyProcessExit converts it into an ordinary JS Error so the pool layer can treat it as a component failure and recover.","triggerScenarios":"Running the wasm worker path when the guest requests process exit — typically the hard memory-limit path (monty-alloc OOM handling calls exit) or an internal guest abort.","commonSituations":"Browser/Node wasm runs where sandboxed code exhausts max_memory; bugs in guest code paths that reach an exit syscall; users seeing this surfaced as a session/pool error rather than a dead process.","solutions":["Inspect the sandboxed code for memory-exhausting patterns and set/raise max_memory appropriately","Treat the thrown error as a worker crash: recreate the pool/session and retry the workload","If reproducible with small inputs, report it — a benign script should never reach the exit syscall"],"exampleFix":"// before\nawait session.feedRun(hugeInputCode)\n// after\ntry {\n  await session.feedRun(code, { maxMemory: 64 * 1024 * 1024 })\n} catch (e) {\n  pool = await Monty.create() // replace crashed worker\n}","handlingStrategy":"try-catch","validationCode":"null","typeGuard":"null","tryCatchPattern":"try { await session.feedRun(code) } catch (e) { if (e.message.includes('requested process exit')) { await pool.close(); pool = await Monty.create(); /* retry once */ } else throw e }","preventionTips":["Set a realistic max_memory so guest code exits gracefully with MemoryError instead of hitting the hard limit","Profile sandboxed scripts for unbounded allocations before deploying","Always recreate the pool/session after this error — the worker is not reusable","Keep the wasm worker packages in sync to avoid guest/host version skew"],"tags":["wasm","wasi","process-exit","memory-limit"],"backgroundTag":"internal-invariant-violation","analyzedSha":"adc986b362e3961f407868cb118a99fe831b9e61","analyzedAt":"2026-09-13T19:19:18.698Z","contentChangedAt":"2026-09-13T19:19:18.698Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}