{"record":{"id":"1dcf1946debb361e","repo":"moeru-ai/airi","slug":"expected-cap-run-list-json-to-return-a-json","errorCode":null,"errorMessage":"Expected `cap run --list --json` to return a JSON array.","messagePattern":"Expected `cap run --list --json` to return a JSON array\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/cap-vite/src/native.ts","lineNumber":98,"sourceCode":"    ['app', 'src', 'main', 'res', 'xml', 'config.xml'],\n    ['app', 'capacitor.build.gradle'],\n    ['capacitor-cordova-android-plugins'],\n    ['capacitor.settings.gradle'],\n  ],\n}\n\nexport function parseCapacitorPlatform(value: string | undefined): CapacitorPlatform | null {\n  return value === 'android' || value === 'ios' ? value : null\n}\n\nexport function hasCapacitorTargetArg(capArgs: string[]): boolean {\n  return capArgs.some((arg, index) => arg === '--target' || (index > 0 && arg.startsWith('--target=')))\n}\n\nfunction parseCapacitorTargetList(value: string): CapacitorTarget[] {\n  const parsed = JSON.parse(value)\n  if (!Array.isArray(parsed)) {\n    throw new TypeError('Expected `cap run --list --json` to return a JSON array.')\n  }\n\n  return parsed\n    .filter((target): target is CapacitorTarget => typeof target === 'object' && target !== null && typeof (target as CapacitorTarget).id === 'string')\n}\n\nasync function listCapacitorTargets(platform: CapacitorPlatform): Promise<CapacitorTarget[]> {\n  const output = await x('cap', ['run', platform, '--list', '--json'])\n\n  return parseCapacitorTargetList(output.stdout)\n}\n\n/**\n * Resolves Capacitor run arguments by applying target defaults.\n *\n * Use when:\n * - `cap-vite` is about to run `cap run`\n * - Callers want env-based device IDs before falling back to the first available target","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/cap-vite/src/native.ts#L80-L116","documentation":"To auto-select a device, cap-vite runs `cap run <platform> --list --json` and expects stdout to be a JSON array; parseCapacitorTargetList throws this TypeError when JSON.parse succeeded but the top-level value is not an array (e.g. an object payload). Note that non-JSON stdout instead surfaces as a SyntaxError from JSON.parse itself.","triggerScenarios":"An @capacitor/cli version whose --list --json emits an object or differently shaped payload; stdout polluted by extra log output that still parses as JSON but not as an array; a wrapper `cap` binary printing its own structure.","commonSituations":"Version drift between the locally installed @capacitor/cli and what cap-vite was built against; a global `cap` shadowing the project one via npx/PATH; plugin logs routed to stdout in CI.","solutions":["Run `npx cap run ios --list --json` yourself and inspect the actual stdout shape","Align the project's @capacitor/cli version with the version cap-vite depends on (or update cap-vite)","Ensure the project-local cap binary is the one resolved (npx from the project root), not a stale global install","If output shape legitimately changed, report it upstream to cap-vite with the captured JSON"],"exampleFix":"# before\n# trust `cap run ios --list --json` output shape blindly\n\n# after\n$ npx cap run ios --list --json   # inspect stdout; it must be a JSON array like [{\"id\":\"...\",\"name\":\"...\"}]\n$ pnpm update @capacitor/cli      # align versions if the shape differs","handlingStrategy":"try-catch","validationCode":"// Sanity-check the CLI output shape before trusting it\nconst output = await x('cap', ['run', platform, '--list', '--json'])\nconst trimmed = output.stdout.trim()\nif (!trimmed.startsWith('['))\n  throw new Error(`cap --list did not emit a JSON array: ${trimmed.slice(0, 200)}`)","typeGuard":"function isCapacitorTargetList(v: unknown): v is Array<{ id: string }> {\n  return Array.isArray(v) && v.every(t => typeof t === 'object' && t !== null && typeof (t as { id?: unknown }).id === 'string')\n}","tryCatchPattern":"try {\n  const targets = await listCapacitorTargets(platform)\n}\ncatch (err) {\n  if (err instanceof TypeError || err instanceof SyntaxError) {\n    // inspect actual `npx cap run <platform> --list --json` output; likely a CLI version mismatch\n    logCapListOutput(platform)\n  }\n  throw err\n}","preventionTips":["Pin the @capacitor/cli version in the project so output shape is deterministic","Run `npx cap run <platform> --list --json` after any Capacitor upgrade","Keep CLI diagnostics on stderr so stdout stays parseable"],"tags":["capacitor","cli","json","parsing"],"backgroundTag":"unexpected-cli-json-output","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","contentChangedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}