can1357/oh-my-pi · error · Error
Cannot set cwd on a disposed JS runtime
Error message
Cannot set cwd on a disposed JS runtime
What it means
`setCwd` explicitly checks `#disposed` and throws `Cannot set cwd on a disposed JS runtime`. The comment documents why the throw is deliberate but guarded: WorkerCore/browser/cmux call setCwd from init/pre-run paths that can race another same-realm runtime, and an escaping throw used to become a fatal unhandledRejection that killed the whole session. Callers must treat this as a signal to recreate the runtime.
Source
Thrown at packages/coding-agent/src/eval/js/shared/runtime.ts:217
this.sessionId = opts.sessionId;
this.#env = new Map();
this.#moduleLoader = new LocalModuleLoader(this.sessionId);
this.#localRoots = opts.localRoots ?? {};
this.helpers = createHelpers({
cwd: () => this.#activeCwd(),
env: this.#env,
localRoots: () => this.#localRoots,
emitStatus: event => this.#activeHooks("emitStatus")?.onDisplay({ type: "status", event }),
});
this.#install(opts.extraGlobals);
}
get cwd(): string {
return this.#cwd;
}
setCwd(cwd: string): void {
if (this.#disposed) throw new Error("Cannot set cwd on a disposed JS runtime");
// Always stamp the runtime and session state: WorkerCore/browser/cmux call
// setCwd from init and pre-run paths that may race another same-realm
// runtime, and a throw here used to escape the inline-worker microtask
// path as a fatal unhandledRejection that killed the whole session.
// #session is the same object saved in this owner's global stack entry,
// so the new cwd survives deferred activation and is visible to this
// runtime's next run; run()/setRunScope still assert exclusive ownership.
this.#cwd = cwd;
this.#session.cwd = cwd;
if (activeGlobalRunOwner === null || activeGlobalRunOwner === this.#globalOwner) {
this.#activateGlobals("set cwd");
}
}
/**
* Install per-run globals. Intended for run-scoped state (browser's `tab`, `display`
* overrides, etc.). Overwrites previous assignments — caller is responsible for any
* cleanup it wants.View on GitHub (pinned to 9690622007)
Solutions
- Guard the setCwd call with a disposed/liveness check on the runtime before invoking it.
- Wrap init/pre-run cwd updates in try-catch and treat disposal as a no-op (abort the stale path) rather than a fatal error.
- Recreate the runtime and re-apply the cwd to the new instance if the cwd change must take effect.
Example fix
// before
runtime.setCwd(newCwd); // may throw fatal unhandledRejection if disposed
// after
try {
runtime.setCwd(newCwd);
} catch (err) {
if (!(err instanceof Error && err.message.includes("disposed"))) throw err;
// stale runtime: drop it; next run creates a fresh one with the current cwd
} Defensive patterns
Strategy: try-catch
Validate before calling
if (runtimeDisposed) return; // skip stale cwd stamp
Try / catch
try {
runtime.setCwd(cwd);
} catch (err) {
if (!(err instanceof Error && err.message === "Cannot set cwd on a disposed JS runtime")) throw err;
// stale runtime raced teardown: drop it; next run recreates with current cwd
} Prevention
- Guard init/pre-run cwd updates with the runtime's disposed flag.
- Deliver cwd changes through the session owner so disposed runtimes are skipped, not stamped.
- Never fire setCwd from async callbacks that can resolve after session teardown.
When it happens
Trigger: Calling `runtime.setCwd(newCwd)` after the runtime was disposed — typically from an inline-worker init or pre-run path racing session teardown, or deferred activation code re-stamping cwd on a dead runtime.
Common situations: Same-realm worker fallback where two runtimes share a global and teardown of one disposes the other's cwd stamp; asynchronous init resolving after the session was killed; session cwd change events delivered post-dispose.
Related errors
- Cannot ${action} on a disposed JS runtime
- Server "${name}" was disconnected during initial connection
- Server "${name}" was disconnected during reconnection
- Python execution is unavailable while session disposal is in
- Recipient session is disposed.
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/fa8ca6a72ba162f7.
Report an issue: GitHub.