moeru-ai/airi · error · 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
The generated wrapper config parses the CAP_VITE_CAP_ARGS_JSON environment variable, which runCapVite sets via JSON.stringify(capArgs). It throws when the variable is set but is not a JSON array whose elements are all strings — usually someone set it by hand or double-encoded it.
Solutions
- Set it as a JSON string array: CAP_VITE_CAP_ARGS_JSON='["ios","--target","iPhone 16 Pro"]'
- Better: don't set it manually — invoke via `cap-vite -- ios ...` or runCapVite(), which serializes capArgs correctly
- Unset the variable when running plain vite builds that don't go through the wrapper
Example fix
# before CAP_VITE_CAP_ARGS_JSON='ios --target "iPhone 16 Pro"' vite --config .cap-vite.config.ts # after CAP_VITE_CAP_ARGS_JSON='["ios","--target","iPhone 16 Pro"]' vite --config .cap-vite.config.ts
Defensive patterns
Strategy: validation
Validate before calling
// When setting the env yourself, always serialize an array of strings process.env.CAP_VITE_CAP_ARGS_JSON = JSON.stringify(['ios', '--target', 'iPhone 16 Pro'])
Type guard
function isStringArray(v: unknown): v is string[] {
return Array.isArray(v) && v.every(x => typeof x === 'string')
} Prevention
- Prefer invoking via `cap-vite -- <platform>` or runCapVite() which sets the env correctly
- Never hand-write the value as a plain argument string
- Unset the variable for vite runs that bypass the wrapper
When it happens
Trigger: Setting CAP_VITE_CAP_ARGS_JSON='ios --target x' (a plain string, not JSON), '["ios", 1]' (non-string element), or a JSON.stringify-ed string that gets stringified again (double encoding). Running the wrapper vite config directly with a stale/incorrect env value.
Common situations: Manually invoking `vite --config <wrapper>` in CI and hand-writing the env var; env value carried over from a different tooling version; quoting layers in YAML/scripts mangling the JSON.
Related errors
- Expected `cap run --list --json` to return a JSON array.
- The first `cap run` argument must be `ios` or `android`.
- The first `cap run` argument must be `ios` or `android`.
- Beat Sync is not available in Stage Pocket
- cap-vite [vite args...] -- <ios|android> [cap run args...]
AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18).
Data as JSON: /api/errors/2ade96e160f2fb4a.
Report an issue: GitHub.
Appendix: 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 677329427f)