can1357/oh-my-pi · error

Session cannot accept launch completion delivery

Error message

Session cannot accept launch completion delivery

What it means

The launch completion sink throws this when the notification arrives on a live session but `session.queueLaunchCompletion` is missing or returns falsy — the session exists but cannot accept the queued completion. Either the optional method is absent on this session implementation or it refuses the delivery (e.g. wrong owner or already drained).

Source

Thrown at packages/coding-agent/src/tools/hub/launch.ts:77

	owner: string,
): CompletionLease | undefined {
	if (!session.queueLaunchCompletion) return undefined;
	let clients = completionRegistrations.get(session);
	if (!clients) {
		clients = new Map();
		completionRegistrations.set(session, clients);
	}
	let owners = clients.get(client);
	if (!owners) {
		owners = new Map();
		clients.set(client, owners);
	}
	let registration = owners.get(owner);
	if (!registration) {
		const unregister = client.onCompletion(owner, notification => {
			if (session.isDisposed?.()) throw new Error("Session disposed before launch completion delivery");
			const delivery = session.queueLaunchCompletion?.(notification);
			if (!delivery) throw new Error("Session cannot accept launch completion delivery");
			return delivery;
		});
		let unregisterDispose: (() => void) | void;
		let unregisterSessionChange: (() => void) | void;
		const cleanup = (preservePending = false): void => {
			if (!registration?.active) return;
			registration.active = false;
			unregister({ preservePending });
			unregisterDispose?.();
			unregisterSessionChange?.();
			owners.delete(owner);
			if (owners.size === 0) clients.delete(client);
			if (clients.size === 0) completionRegistrations.delete(session);
		};
		registration = { inFlight: 0, retained: false, active: true, cleanup };
		owners.set(owner, registration);
		unregisterDispose = session.registerDisposeCallback?.(() => cleanup(true));
		unregisterSessionChange = session.registerSessionChangeCallback?.(() => cleanup(true));

View on GitHub (pinned to 9690622007)

Solutions

  1. Ensure the ToolSession passed to the launch tool implements queueLaunchCompletion(notification) and returns a truthy delivery.
  2. Update the session implementation / hub tool so both sides agree on the launch-completion contract.
  3. Check that the launch was not already resolved/drained by another path before the notification arrived.
Defensive patterns

Strategy: type-guard

Validate before calling

// Verify the session supports launch completions before using the launch tool:
if (typeof session.queueLaunchCompletion !== "function") {
  throw new Error("session does not support launch completion delivery");
}

Type guard

function supportsLaunchCompletion(s: ToolSession): boolean {
  return typeof (s as ToolSession).queueLaunchCompletion === "function";
}

Try / catch

try {
  await launchTool.run({ op: "start", name, application });
} catch (err) {
  if (err instanceof Error && err.message === "Session cannot accept launch completion delivery") {
    // use/upgrade a session implementation with queueLaunchCompletion support
  } else throw err;
}

Prevention

When it happens

Trigger: client.onCompletion callback fires with a live session, but `session.queueLaunchCompletion?.(notification)` is undefined — either the session type lacks queueLaunchCompletion (optional-call `?.`) or it returns null/undefined for the notification.

Common situations: Embedding the tool against a custom/trimmed ToolSession implementation that never implemented queueLaunchCompletion; session already processed or invalidated the launch so it declines queuing; version mismatch between the hub tool code and the session object passed in.

Related errors


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