{"record":{"id":"51f383d89a072b16","repo":"clockworklabs/SpacetimeDB","slug":"js-worker-exited-before-replying-to-ctx","errorCode":null,"errorMessage":"JS worker exited before replying to `{ctx}`","messagePattern":"JS worker exited before replying to `(.+?)`","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/core/src/host/v8/mod.rs","lineNumber":750,"sourceCode":"    }\n}\n\nasync fn send_js_request<Req, T>(\n    ctx: &'static str,\n    tx: &mpsc::Sender<Req>,\n    request: impl FnOnce(JsReplyTx<T>) -> Req,\n) -> T\nwhere\n    Req: Send + 'static,\n{\n    let (reply_tx, reply_rx) = oneshot::channel();\n    if tx.send(request(reply_tx)).await.is_err() {\n        panic!(\"JS worker exited before accepting `{ctx}`\");\n    }\n    match reply_rx.await {\n        Ok(Ok(value)) => value,\n        Ok(Err(panic)) => panic::resume_unwind(panic),\n        Err(_) => panic!(\"JS worker exited before replying to `{ctx}`\"),\n    }\n}\n\nasync fn send_js_unbounded_request<T>(\n    ctx: &'static str,\n    tx: &MeteredUnboundedSender<JsMainWorkerRequest>,\n    request: impl FnOnce(JsReplyTx<T>) -> JsMainWorkerRequest,\n) -> T {\n    let (reply_tx, reply_rx) = oneshot::channel();\n    if tx.send(request(reply_tx)).is_err() {\n        panic!(\"JS worker exited before accepting `{ctx}`\");\n    }\n    match reply_rx.await {\n        Ok(Ok(value)) => value,\n        Ok(Err(panic)) => panic::resume_unwind(panic),\n        Err(_) => panic!(\"JS worker exited before replying to `{ctx}`\"),\n    }\n}","sourceCodeStart":732,"sourceCodeEnd":768,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/9e0d92412ff2248f401a8ad12d535f2b5ac30912/crates/core/src/host/v8/mod.rs#L732-L768","documentation":"Host-side panic in SpacetimeDB's V8 host: a JS request was accepted by the worker (the send succeeded) but the reply channel was dropped without a reply — the oneshot receiver returned Err. This means the JS worker exited after taking the request but before answering, i.e. it crashed or was torn down mid-request. Any panic payload the worker did propagate arrives via the Ok(Err(panic)) arm and is resumed as the original panic; this Err(_) arm is specifically 'worker died silently'.","triggerScenarios":"The JS worker aborting while executing the request: uncaught exception paths that skip the reply, V8 fatal errors (OOM, stack overflow), or the host tearing down the worker during deploy/shutdown while a procedure call is in flight.","commonSituations":"Long-running JS procedures that exhaust memory; redeploying a module while scheduled procedures execute; JS SDK/runtime mismatches causing the worker to bail.","solutions":["Check host logs immediately preceding this panic for the worker's termination reason and address it (fix the module code, raise memory limits).","Keep procedures short and free of unbounded loops/allocations so they complete within worker lifetime.","Republish with matching JS SDK and server versions.","Avoid issuing calls during redeploy windows; if the race recurs on current versions, report it to SpacetimeDB with the request context string."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Before awaiting a JS request, verify the worker is still alive:\nif js_instance.is_closed() {\n    return Err(HostError::js_worker_unavailable(ctx_name));\n}\n// After send succeeds, wrap the await in a task to observe worker death:\nlet ret = tokio::spawn(js_instance.call_procedure(params)).await\n    .map_err(|_| HostError::js_worker_died_mid_request(ctx_name))?;","typeGuard":null,"tryCatchPattern":"match reply_rx.await {\n    Ok(Ok(value)) => Ok(value),\n    Ok(Err(panic)) => { log::error!(\"JS procedure panicked: {panic:?}\"); Err(HostError::js_module_panic) }\n    Err(_) => { log::error!(\"JS worker died mid-request `{ctx}`\"); Err(HostError::js_worker_died) }\n}","preventionTips":["Bound memory and iteration in JS procedures so workers cannot be OOM-killed mid-call.","Log and fix the first worker crash — this panic is always a downstream symptom.","Avoid issuing JS calls during module redeploy or host shutdown windows."],"tags":["spacetimedb","javascript","v8","worker-crash","request-timeout","host-panic"],"backgroundTag":"worker-thread-crashed","analyzedSha":"9e0d92412ff2248f401a8ad12d535f2b5ac30912","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}