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
- Re-open (or reconfigure) the computer session with read_only: false if mutation is intended.
- Remove or branch around mutating calls when operating in read-only mode; use screenshots/queries only.
- 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
- Generate read-only-safe code when the session is opened with read_only: true.
- Check context.readOnly before any mutating facade call in scripts.
- Document the read_only flag in prompts so the model doesn't attempt mutations.
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
- LSP action ${action} is disabled in this read-only session
- {}: {error}
- inter-device move failed: {} to {}; unable to remove target:
- Permission denied
- cannot stat {file}: {error}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/1f0dc141f05c48b9.
Report an issue: GitHub.