moeru-ai/airi · error · Error
JSON.stringify(result)
Error message
JSON.stringify(result)
What it means
The computer_use tool's execute callback throws the raw JSON-serialized command result whenever the shell command exits with a non-zero exit code. The stringified result (stdout, stderr, exitCode) becomes the error message; it is not a library bug but an intentional propagation of a failed command executed on the local machine via the computer-use client.
Solutions
- Inspect the thrown message (it is JSON); parse it and read stdout/stderr/exitCode to see the underlying command failure.
- Fix the argv the agent/Caller passed: verify the binary exists in the computer-use environment and flags are valid.
- If the command legitimately exits non-zero, catch the error and treat the parsed result as normal tool output instead of a hard failure.
- Check the computer-use service/storage setup if commands that should succeed consistently fail.
Example fix
// before
execute: async (input) => {
const result = await client().run(input as { argv: string[] })
if (result.exitCode !== 0)
throw new Error(JSON.stringify(result))
return JSON.stringify(result)
}
// after
execute: async (input) => {
const result = await client().run(input as { argv: string[] })
if (result.exitCode !== 0)
throw new Error(`computer_use failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`)
return JSON.stringify(result)
} Defensive patterns
Strategy: try-catch
Validate before calling
const known = ['ls','cat','pwd','echo']
if (!known.includes(argv[0])) throw new Error(`command may not exist in computer-use env: ${argv[0]}`) Type guard
function commandFailed(result: { exitCode: number }): boolean {
return result.exitCode !== 0
} Try / catch
try {
const out = await computerUseTool.execute({ argv })
} catch (err) {
try {
const result = JSON.parse((err as Error).message)
console.error(`exit ${result.exitCode}: ${result.stderr}`)
} catch {
console.error(err)
}
} Prevention
- Parse the error message as JSON to recover stdout/stderr/exitCode.
- Constrain the agent's argv to commands known to exist in the computer-use environment.
- Treat non-zero exit codes (grep, diff) as expected results, not fatal errors.
- Verify PATH and sandbox permissions in the computer-use service config.
When it happens
Trigger: client().run({ argv }) returns exitCode !== 0 — the executed argv refers to a missing binary, a command that failed (bad flags, non-zero exit path), or a sandboxed environment where the command cannot run.
Common situations: LLM agent issues computer_use with an invalid or unavailable command; permission or PATH differences inside the computer-use sandbox; command writes to stderr and exits non-zero (e.g. grep with no matches, diff on differing files).
Related errors
- Assistant message does not contain tool call
- [llm-streaming-control] handler failed
- Select this tool before running it again.
- The selected invocation does not match the tool name.
- Tool call " " is ambiguous. Select an invocation.
AI-assisted analysis of moeru-ai/airi@438a067dde (2026-09-17).
Data as JSON: /api/errors/adaa6187278ebdf9.
Report an issue: GitHub.
Appendix: source
Thrown at apps/stage-tamagotchi/src/renderer/stores/tools/builtin/computer-use.ts:38
invokers ??= createInvokers()
return invokers
}
return [
rawTool({
name: 'computer_use',
description: 'Control native desktop apps, inspect windows, capture screenshots, and use keyboard or mouse input. On macOS, call app.probePermissions before visual tasks. If screen_recording is missing, ask the user to grant permission; captures can contain only a blank background. Start with argv ["invoke", "--help"], then inspect command help. Pass each CLI argument separately. Use explicit window targets when available. Preserve failure_details and verified metadata: exitCode 0 does not prove the intended UI effect. Use computer_use_read_image to view screenshot artifact paths. This tool acts on the local computer.',
parameters: {
type: 'object',
properties: {
argv: { type: 'array', items: { type: 'string' }, description: 'AUV arguments beginning with invoke, excluding the executable name.' },
},
required: ['argv'],
additionalProperties: false,
},
execute: async (input) => {
const result = await client().run(input as { argv: string[] })
if (result.exitCode !== 0)
throw new Error(JSON.stringify(result))
return JSON.stringify(result)
},
}),
rawTool({
name: 'computer_use_read_image',
description: 'View a PNG or JPEG screenshot artifact produced by computer_use. Only files inside AIRI computer-use storage can be read. Select this tool together with computer_use for visual tasks.',
parameters: {
type: 'object',
properties: { path: { type: 'string', description: 'Absolute screenshot artifact path returned by computer_use.' } },
required: ['path'],
additionalProperties: false,
},
execute: async input => [{ type: 'image_url', image_url: { url: await client().readImage(input as { path: string }) } }],
}),
]
}
View on GitHub (pinned to 438a067dde)