can1357/oh-my-pi · error · ToolError

read-only run: '${method}' requires read_only: false

Error message

read-only run: '${method}' requires read_only: false

What it means

The computer worker runs in a read-only mode where mutating desktop operations are forbidden. guardRun() is invoked by every mutating facade method (setValue, perform, press, click, focus, doubleClick); if the run context has readOnly=true, the call throws this ToolError before touching the desktop.

Source

Thrown at packages/coding-agent/src/tools/computer/worker.ts:178

		? chord
				.split("+")
				.map(key => key.trim())
				.filter(Boolean)
		: chord;
}

function matchesFilter(window: DesktopWindow, filter?: WindowFilter): boolean {
	if (!filter) return true;
	const app = filter.app?.toLocaleLowerCase();
	const title = filter.title?.toLocaleLowerCase();
	return (
		(!app || window.app.toLocaleLowerCase().includes(app)) &&
		(!title || window.title.toLocaleLowerCase().includes(title))
	);
}

function guardRun(context: ComputerRunContext, method: string): void {
	if (context.readOnly) throw new ToolError(`read-only run: '${method}' requires read_only: false`);
	throwIfAborted(context.signal);
}

async function captureScreenshot(
	session: NativeDesktopSession,
	getContext: RunContextAccessor,
	target: string,
	options?: ScreenshotOptions,
): Promise<{ path: string; width: number; height: number }> {
	const context = getContext();
	const frame = await nativeCall(context.signal, () =>
		session.capture(target, {
			maxWidth: context.snapshot.captureMaxWidth,
			maxHeight: context.snapshot.captureMaxHeight,
		}),
	);
	const destination = path.join(os.tmpdir(), `omp-computer-${Snowflake.next()}.png`);
	await Bun.write(destination, frame.data);

View on GitHub (pinned to 9690622007)

Solutions

  1. Re-open (or reconfigure) the computer session with read_only: false if mutation is intended.
  2. Remove or branch around mutating calls when operating in read-only mode; use screenshots/queries only.
  3. Check context.readOnly in generated code before calling mutating methods.

Example fix

// inside computer run code
// before
await desktop.win({ app: "Notes" }).click();

// after
if (!context.readOnly) {
  await desktop.win({ app: "Notes" }).click();
} else {
  await desktop.screenshot(); // read-only alternative
}
Defensive patterns

Strategy: validation

Validate before calling

// inside computer run code
if (context.readOnly) {
  throw new Error("cannot click/press/setValue: session is read-only");
}

Try / catch

try {
  await run(code);
} catch (err) {
  if (err instanceof ToolError && /read-only run/.test(err.message)) {
    // fall back to observation-only operations (screenshot, query)
  } else throw err;
}

Prevention

When it happens

Trigger: Executing computer-run code that calls click()/press()/setValue()/perform()/focus()/doubleClick() while the tool was opened with read_only: true.

Common situations: An agent or script tries to interact with the UI during a screenshot/inspection-only session; the session config defaulted to read-only; policy restricts the tool to observation but generated code attempts mutation.

Related errors


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