can1357/oh-my-pi · error · ToolError
no active computer run
Error message
no active computer run
What it means
Desktop facade objects resolve their run context via AsyncLocalStorage (#runContexts). #currentRunContext() throws 'no active computer run' when a facade method is invoked outside an active run — i.e. the desktop scope was captured/escaped from the run callback and called later, or a bound facade is invoked where no run context is stored.
Source
Thrown at packages/coding-agent/src/tools/computer/worker.ts:635
async #callTool(active: ActiveRun, name: string, args: unknown): Promise<unknown> {
const id = `computer-tc-${active.id}-${crypto.randomUUID()}`;
const { promise, resolve, reject } = Promise.withResolvers<unknown>();
active.pendingTools.set(id, { resolve, reject });
this.#transport.send({ type: "tool-call", id, runId: active.id, name, args });
return await promise;
}
#deliverToolReply(id: string, reply: ToolReply): void {
const pending = this.#active?.pendingTools.get(id);
if (!pending) return;
this.#active?.pendingTools.delete(id);
if (reply.ok) pending.resolve(reply.value);
else pending.reject(replyError(reply.error));
}
#currentRunContext = (): ComputerRunContext => {
const context = this.#runContexts.getStore();
if (!context) throw new ToolError("no active computer run");
return context;
};
#createDesktopScope(session: NativeDesktopSession): object {
const getContext = this.#currentRunContext;
const makeWin = (window: DesktopWindow): Win => new Win(session, getContext, window);
const el = (node: AxNode): El => new El(session, getContext, node);
const desktopTarget = new Win(session, getContext, {
id: "desktop",
app: "desktop",
title: "desktop",
x: 0,
y: 0,
width: 0,
height: 0,
focused: false,
});
return {View on GitHub (pinned to 9690622007)
Solutions
- Perform all desktop interactions synchronously within the computer-run callback scope.
- Do not capture/alias the desktop object outside the run; re-run a new computer run for later interactions.
- If async work must continue, chain it inside the run before returning so the AsyncLocalStorage context is active.
Example fix
// inside computer run code // before window.__desktop = desktop; setTimeout(() => window.__desktop.screenshot(), 1000); // throws // after await wait(1000); // stay inside the run await desktop.screenshot(); // context still active
Defensive patterns
Strategy: validation
Validate before calling
// don't escape the facade: do all desktop work inside the run callback
// bad: const d = desktop; later d.screenshot()
// good:
await (async () => { await desktop.screenshot(); })(); // stays in run scope Try / catch
try {
await escapedFacade.screenshot();
} catch (err) {
if (err instanceof ToolError && err.message === "no active computer run") {
// re-dispatch inside a new computer run
} else throw err;
} Prevention
- Never store the desktop object in outer variables, globals, or closures that outlive the run callback.
- Await all async work inside the run before returning, so AsyncLocalStorage context stays active.
- Structure scripts as one run per interaction batch rather than capturing the facade for later use.
When it happens
Trigger: Calling a desktop facade method (screenshot, win, click, …) after the run finished (callback returned), storing the desktop object in a global/outer variable and using it asynchronously beyond the run, or invoking a bound facade from a worker message handler outside the run scope.
Common situations: Agent scripts save `const d = desktop` and call d.screenshot() in a later tick/callback; a promise started inside the run resolves after the AsyncLocalStorage context is gone; facade objects leak into timers or event handlers.
Related errors
- Plugin "${pluginId}" is installed in both user and project s
- Plugin "${pluginId}" is installed in both user and project s
- project-scoped install requires running inside a project dir
- Security finding path is outside the immutable scan scope: $
- ${operation} requires an active cmux browser run
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/a1f102d9fb8d5c2f.
Report an issue: GitHub.