moeru-ai/airi · error

CAP_VITE_CAP_ARGS_JSON must be a JSON string array.

Error message

CAP_VITE_CAP_ARGS_JSON must be a JSON string array.

What it means

Thrown by parseCapArgs() inside vite-wrapper-config.ts when process.env.CAP_VITE_CAP_ARGS_JSON is set but does not JSON.parse into an array of strings. It guards the env-var contract that runCapVite establishes when it spawns the wrapper Vite process.

Source

Thrown at packages/cap-vite/src/vite-wrapper-config.ts:15

import process from 'node:process'

import { defineConfig, loadConfigFromFile, mergeConfig } from 'vite'

import { capVitePlugin } from './vite-plugin'

function parseCapArgs(): string[] {
  const value = process.env.CAP_VITE_CAP_ARGS_JSON
  if (!value) {
    return []
  }

  const parsed = JSON.parse(value)
  if (!Array.isArray(parsed) || parsed.some(arg => typeof arg !== 'string')) {
    throw new Error('CAP_VITE_CAP_ARGS_JSON must be a JSON string array.')
  }

  return parsed
}

function parseConfigLoader(): 'bundle' | 'native' | 'runner' | undefined {
  const value = process.env.CAP_VITE_CONFIG_LOADER
  if (value === 'bundle' || value === 'native' || value === 'runner') {
    return value
  }

  return undefined
}

export default defineConfig(async (env) => {
  const root = process.env.CAP_VITE_ROOT ?? process.cwd()
  const baseConfigFile = process.env.CAP_VITE_BASE_CONFIG || undefined
  const configLoader = parseConfigLoader()

View on GitHub (pinned to 27111382b4)

Solutions

  1. Set CAP_VITE_CAP_ARGS_JSON to JSON.stringify(['ios']) style values only.
  2. Let runCapVite() own the env var; avoid setting it by hand.
  3. If scripting, validate with Array.isArray(parsed) && parsed.every(x => typeof x === 'string') before assigning the env.

Example fix

// before
process.env.CAP_VITE_CAP_ARGS_JSON = JSON.stringify({ platform: 'ios' })
// after
process.env.CAP_VITE_CAP_ARGS_JSON = JSON.stringify(['ios'])
Defensive patterns

Strategy: validation

Validate before calling

function readCapArgsEnv(): string[] {
  const raw = process.env.CAP_VITE_CAP_ARGS_JSON
  if (!raw) return []
  const parsed = JSON.parse(raw) as unknown
  if (!Array.isArray(parsed) || parsed.some(a => typeof a !== 'string')) {
    throw new Error('CAP_VITE_CAP_ARGS_JSON must be set to a JSON string array.')
  }
  return parsed
}

Type guard

function isStringArray(value: unknown): value is string[] {
  return Array.isArray(value) && value.every(v => typeof v === 'string')
}

Try / catch

try {
  parseCapArgs()
} catch (error) {
  if (error instanceof Error && error.message.includes('JSON string array')) {
    console.error('Fix CAP_VITE_CAP_ARGS_JSON; it must be a JSON-encoded string[].')
  }
  throw error
}

Prevention

When it happens

Trigger: CAP_VITE_CAP_ARGS_JSON is set to a JSON object, a JSON scalar, a non-JSON string, or an array containing non-string elements (numbers, null). JSON.parse itself throwing (malformed JSON) propagates a SyntaxError before this guard; this guard specifically catches the shape mismatch.

Common situations: Manually exporting the env var with a wrong shape in a script; a build tool that stringifies an object instead of an array; copy-paste of a CLI arg string without JSON encoding; the env var surviving from an experiment that put objects in it.

Related errors


AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12). Data as JSON: /api/errors/2ade96e160f2fb4a. Report an issue: GitHub.