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

  1. Inspect the thrown message (it is JSON); parse it and read stdout/stderr/exitCode to see the underlying command failure.
  2. Fix the argv the agent/Caller passed: verify the binary exists in the computer-use environment and flags are valid.
  3. If the command legitimately exits non-zero, catch the error and treat the parsed result as normal tool output instead of a hard failure.
  4. 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

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


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)