can1357/oh-my-pi · error · ToolError

Vibe session "${record.id}" is dead. Spawn a new one with vi

Error message

Vibe session "${record.id}" is dead. Spawn a new one with vibe_spawn.

What it means

VibeSessionRegistry.send() refuses to deliver a message to a vibe worker whose record is in the 'dead' state. A dead record means the worker spawned but terminally failed (crashed, was killed, or its spawn/turn failed permanently) and can no longer accept messages. The error explicitly directs the caller to spawn a replacement worker with vibe_spawn.

Source

Thrown at packages/coding-agent/src/vibe/runtime.ts:939

				if (!record.terminalPersisted) {
					throw new ToolError("Vibe parent session changed before spawn failure could be persisted.");
				}
			}
			this.#records.delete(key);
			throw error;
		}
	}

	/**
	 * Send a message to a worker. Mid-turn and streaming → steering; mid-turn
	 * otherwise → queued for the next turn; idle/parked → starts a new
	 * background turn immediately.
	 */
	async send(session: ToolSession, args: { session: string; message: string }): Promise<VibeSendOutcome> {
		const scope = this.ownerScope(session);
		const record = this.#record(scope, args.session);
		if (record.state === "dead") {
			throw new ToolError(`Vibe session "${record.id}" is dead. Spawn a new one with vibe_spawn.`);
		}
		const message = args.message.trim();
		if (!message) throw new ToolError("Message must not be empty.");
		const registered = this.#registeredAgent(record);
		if (AgentRegistry.global().get(record.id) && !registered) {
			throw new ToolError(`Vibe session "${record.id}" no longer resolves to this parent session.`);
		}

		if (record.turn) {
			const live = registered?.session;
			if (live?.isStreaming) {
				await live.steer(message);
				record.lastActivityAt = Date.now();
				return { id: record.id, mode: "steered" };
			}
			record.queue.push(message);
			record.lastActivityAt = Date.now();
			return { id: record.id, mode: "queued" };

View on GitHub (pinned to 9690622007)

Solutions

  1. Spawn a new worker with vibe_spawn (optionally passing the same name to get a successor id) and resend the message to the new session.
  2. Check the session's lastActivity (e.g. 'spawn failed' / kill reason) via vibe_status to understand why it died before respawning.
  3. If the death was caused by a bad prompt or model config, fix the prompt/cli/model args before respawning.
  4. Update orchestration code to handle dead sessions by respawning instead of retrying send.

Example fix

// before
await registry.send(session, { session: deadId, message: 'continue' });
// ToolError: Vibe session "x" is dead.

// after
const spawned = await registry.spawn(session, { cli: 'codex', prompt: 'continue the work' });
await registry.send(session, { session: spawned.id, message: 'continue' });
Defensive patterns

Strategy: validation

Validate before calling

// Look up the record's state before sending
const status = await registry.status(session, { sessions: [id] });
if (status.find(s => s.id === id)?.state === 'dead') {
	// respawn instead of sending
}

Type guard

function isAliveRecord(record: VibeRecord): boolean {
	return record.state !== 'dead';
}

Try / catch

try {
	await registry.send(session, { session: id, message });
} catch (err) {
	if (err instanceof ToolError && err.message.includes('is dead')) {
		const spawned = await registry.spawn(session, { cli, prompt: message });
		return spawned;
	}
	throw err;
}

Prevention

When it happens

Trigger: Calling send(session, { session: '<id>', message }) with the id of a vibe session whose record.state === 'dead' — e.g. after the worker process crashed, was killed via vibe_kill, or a previous turn failed terminally.

Common situations: Agent workflow sends messages to a worker that crashed earlier in the run; reusing a stored session id from a previous task after the worker died; a worker killed due to error/timeout then addressed again by a queued follow-up message.

Related errors


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