can1357/oh-my-pi · error · Error

${this.#options.languageName} kernel is not running

Error message

${this.#options.languageName} kernel is not running

What it means

`KernelBase.execute` checks `isAlive()` (`#alive && !#disposed`) before queueing a code execution. If the kernel process has died, was never fully started, or was disposed, executing code is impossible and it throws `"<language> kernel is not running"`. This prevents sending messages to a dead kernel and hanging on a promise that would never resolve.

Source

Thrown at packages/coding-agent/src/eval/kernel-base.ts:214

		this.#exitedPromise = proc.exited;
		void this.#exitedPromise.then(code => {
			this.#alive = false;
			this.#abortPendingExecutions(`${this.#options.languageName} kernel exited with code ${code}`, {
				kernelKilled: true,
			});
		});

		this.#startReader(proc.stdout as ReadableStream<Uint8Array>);
		this.#startStderrDrain(proc.stderr as ReadableStream<Uint8Array>);
	}

	isAlive(): boolean {
		return this.#alive && !this.#disposed;
	}

	async execute(code: string, options?: TExecuteOptions): Promise<KernelExecuteResult> {
		if (!this.isAlive()) {
			throw new Error(`${this.#options.languageName} kernel is not running`);
		}

		const msgId = options?.id ?? Snowflake.next();
		const { promise, resolve } = Promise.withResolvers<KernelExecuteResult>();
		const pending: PendingExecution = {
			resolve,
			options,
			status: "ok",
			cancelled: false,
			timedOut: false,
			stdinRequested: false,
			settled: false,
			kernelKilled: false,
		};
		this.#pending.set(msgId, pending);

		const finalize = () => {
			if (pending.settled) return;

View on GitHub (pinned to 9690622007)

Solutions

  1. Check `kernel.isAlive()` before executing; restart via `start()` if dead
  2. Recreate the kernel/session when it reports not alive — a dead process cannot be revived
  3. Inspect kernel stderr/trace logs to find why the process exited (missing interpreter, import crash, OOM)

Example fix

// before
const result = await kernel.execute(code);
// after
if (!kernel.isAlive()) {
  kernel = await createKernel(cwd); // restart
}
const result = await kernel.execute(code);
Defensive patterns

Strategy: validation

Validate before calling

if (!kernel.isAlive()) {
  kernel = await createKernel({ cwd }); // restart before use
}

Type guard

function isRunnableKernel(k: KernelBase<never, never> | null): k is KernelBase<never, never> {
  return k !== null && k.isAlive();
}

Try / catch

try {
  return await kernel.execute(code);
} catch (err) {
  if (err instanceof Error && /kernel is not running/.test(err.message)) {
    kernel = await createKernel({ cwd });
    return await kernel.execute(code);
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling `execute(code)` on a kernel after `shutdown()`/`dispose()`, after the kernel process crashed or exited, or before `start()` completed successfully.

Common situations: Long-lived eval sessions whose Python/JS kernel process died (OOM, interpreter error); reusing a cached kernel object after the session was torn down; calling execute before awaiting `start()`.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/e513e34784cbe7e0. Report an issue: GitHub.