stablyai/orca · error · RuntimeClientError

invalid_argument

invalid_argument

Error message

<op> must be grant, revoke, or reset

What it means

Thrown by parseEmulatorPermissionRequest when the required --op flag is set to anything other than 'grant', 'revoke', or 'reset'. The op is the discriminator for the whole request: grant/revoke need a permission (and optionally a package), reset takes neither. An unrecognized op cannot be mapped to an Android pm action, so it is rejected before any further parsing.

Source

Thrown at src/cli/emulator-permissions-args.ts:15

import { getOptionalStringFlag, getRequiredStringFlag } from './flags'
import { RuntimeClientError } from './runtime-client'

export type EmulatorPermissionRequest = {
  op: 'grant' | 'revoke' | 'reset'
  packageName?: string
  permission?: string
}

export function parseEmulatorPermissionRequest(
  flags: Map<string, string | boolean>
): EmulatorPermissionRequest {
  const op = getRequiredStringFlag(flags, 'op')
  if (op !== 'grant' && op !== 'revoke' && op !== 'reset') {
    throw new RuntimeClientError('invalid_argument', '<op> must be grant, revoke, or reset')
  }
  const packageName = getOptionalStringFlag(flags, 'package')
  const permission = getOptionalStringFlag(flags, 'permission')
  if (op === 'reset') {
    if (packageName || permission) {
      throw new RuntimeClientError(
        'invalid_argument',
        'reset does not accept package or permission'
      )
    }
    return { op }
  }
  if (!permission) {
    throw new RuntimeClientError('invalid_argument', `<permission> is required for ${op}`)
  }
  return { op, packageName: packageName ?? getRequiredStringFlag(flags, 'package'), permission }
}

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Pass --op as exactly 'grant', 'revoke', or 'reset'.
  2. If you meant to wipe all permissions for a package, use --op reset (without --package/--permission).
  3. Check the calling script against the EmulatorPermissionRequest type definition.

Example fix

// before
new Map([['op','allow'],['permission','CAMERA']])

// after
new Map([['op','grant'],['permission','CAMERA']])
Defensive patterns

Strategy: type-guard

Validate before calling

const VALID_OPS = new Set(['grant', 'revoke', 'reset'])
function pickOp(flags: Map<string, string | boolean>): 'grant' | 'revoke' | 'reset' {
  const op = flags.get('op')
  if (typeof op !== 'string' || !VALID_OPS.has(op)) {
    throw new Error(`--op must be one of ${[...VALID_OPS].join('|')}`)
  }
  return op as 'grant' | 'revoke' | 'reset'
}

Type guard

function isEmulatorPermissionOp(v: unknown): v is 'grant' | 'revoke' | 'reset' {
  return v === 'grant' || v === 'revoke' || v === 'reset'
}

Try / catch

try {
  parseEmulatorPermissionRequest(flags)
} catch (e) {
  if (e instanceof RuntimeClientError && e.code === 'invalid_argument') {
    // prompt user for a valid --op
  }
  throw e
}

Prevention

When it happens

Trigger: Calling parseEmulatorPermissionRequest with a flags map whose 'op' entry is a string outside the set {grant, revoke, reset}, e.g. `new Map([['op','allow']])` or omitting a value so the parser coerces it incorrectly.

Common situations: Typo in an emulator-permission CLI command (`orca emulator permissions --op grannt`), a script passing a stale op name from an older API, or confusion with the host's own permission verb set.

Related errors


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/d168c1e9137e9ad1. Report an issue: GitHub.