can1357/oh-my-pi · error · ToolError
${operation} requires an active cmux browser run
Error message
${operation} requires an active cmux browser run What it means
CmuxTab methods that need run-scoped state (abort signal, timeouts, run scope) call `#requireRunContext(operation)`, which throws this ToolError when `#runContext` is unset. Browser operations are only valid inside an active cmux browser run; calling them outside one has no execution context.
Source
Thrown at packages/coding-agent/src/tools/browser/cmux/cmux-tab.ts:1130
}
}
#normalizeGeometry(value: unknown): CmuxGeometry {
const object = value && typeof value === "object" ? (value as Record<string, unknown>) : {};
return {
innerWidth: numberFrom(object.innerWidth, DEFAULT_VIEWPORT.width),
innerHeight: numberFrom(object.innerHeight, DEFAULT_VIEWPORT.height),
dpr: numberFrom(object.dpr, DEFAULT_VIEWPORT.deviceScaleFactor ?? 1),
scrollX: numberFrom(object.scrollX, 0),
scrollY: numberFrom(object.scrollY, 0),
scrollWidth: numberFrom(object.scrollWidth, DEFAULT_VIEWPORT.width),
scrollHeight: numberFrom(object.scrollHeight, DEFAULT_VIEWPORT.height),
};
}
#requireRunContext(operation: string): RunContext {
if (!this.#runContext) {
throw new ToolError(`${operation} requires an active cmux browser run`);
}
return this.#runContext;
}
}
class CmuxResponse {
readonly #record: CmuxResponseRecord;
constructor(record: CmuxResponseRecord) {
this.#record = record;
}
url(): string {
return this.#record.url;
}
status(): number {
return this.#record.status;View on GitHub (pinned to 9690622007)
Solutions
- Move the browser calls inside the active cmux browser run block so the run context is installed.
- Don't cache CmuxTab/page references across runs — obtain them within each run's scope.
- Guard async callbacks: check the run is still active (or abort them with the run's signal) before issuing browser calls.
Example fix
// before
const tab = await browser.openTab();
setTimeout(() => tab.navigate(url), 5000); // fires after run ended
// after
await withBrowserRun(async () => {
const tab = await browser.openTab();
await tab.navigate(url);
}); Defensive patterns
Strategy: validation
Validate before calling
// structure code so all browser calls live inside the run scope
if (!runIsActive) throw new Error('browser API used outside cmux run');
await withBrowserRun(async (tab) => { /* all tab calls here */ }); Prevention
- Never retain tab/page/browser handles beyond the run's lifetime — scope them to the run callback.
- Tie background async work to the run's AbortSignal and cancel it in finally.
- Funnel all browser access through a helper that asserts the run context exists.
When it happens
Trigger: Invoking tab/page/browser methods (navigation, eval, screenshots, wait) before a browser run starts, after it finished/aborted, or from a detached/reused CmuxTab instance whose run ended.
Common situations: Calling the facade from test setup code outside the run helper; keeping a tab reference after the run's finally block cleared the context; async callbacks (timers, event handlers) firing after the run completed.
Related errors
- Composer is not available for transfer
- Browser runtime started without an active run
- DAP adapter ${this.adapter.name} is not running
- Debug session ${root.id} is still active. Terminate it befor
- Cannot ${action} on a disposed JS runtime
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/c0730259e1e2d594.
Report an issue: GitHub.