koala73/worldmonitor · error · UsageError
--args must be valid JSON
Error message
--args must be valid JSON: ${err.message} What it means
In the worldmonitor CLI, an explicit --args value is passed verbatim to JSON.parse by collectArgs. Anything JSON.parse rejects — unquoted keys, single-quoted strings, trailing commas, shell-mangled quotes — raises UsageError embedding the parser's message, and run() maps it to exit code 2.
Solutions
- Wrap the JSON in shell single quotes: --args '{"country_code":"IR"}'
- Or drop --args and use per-flag params: --country_code IR (bare boolean flags become true)
- Sanity-check the payload before invoking: echo '<your-json>' | jq .
- On Windows use escaped double quotes or a shell that supports single quotes
Example fix
# before
worldmonitor call get_country_risk --args "{country_code: 'IR',}" # UsageError: --args must be valid JSON
# after
worldmonitor call get_country_risk --args '{"country_code":"IR"}'
# or skip JSON entirely
worldmonitor call get_country_risk --country_code IR Defensive patterns
Strategy: validation
Validate before calling
// Validate --args before spawning the CLI
function parseCliArgs(json) {
try { return { ok: true, value: JSON.parse(json) }; }
catch (e) { return { ok: false, error: e.message }; }
}
const check = parseCliArgs(argsJson);
if (!check.ok) throw new Error(`--args is not valid JSON: ${check.error}`); Type guard
function isJsonObject(v: unknown): v is Record<string, unknown> {
return typeof v === 'object' && v !== null && !Array.isArray(v);
} Prevention
- Prefer per-flag params (--country_code IR) unless nested values are required
- Build --args programmatically (JSON.stringify) instead of string concatenation
- Pipe hand-written JSON through jq before using it in a command line
When it happens
Trigger: --args "{key:'val'}" (unquoted keys or single quotes); a trailing comma; double-quoted JSON whose inner quotes were stripped by the shell; flags accidentally concatenated into the --args value.
Common situations: Writing the JSON without single-quote shell wrapping so quotes and $ interpolate; converting from --key value syntax and leaving fragments behind; Windows cmd quoting rules; missing closing brace from manual editing.
Related errors
- `call` needs a tool name, e.g. `worldmonitor call…
- ` ` needs < >. Usage: worldmonitor < >
- `get` needs an API path, e.g. `worldmonitor get /api/health`
- Unknown command: . Run `worldmonitor --help`.
- bodyTransportFailure ? 'NHC_POINT_REQUEST_FAILED' : 'NHC_POINT_RESPONSE_INVALID'
AI-assisted analysis of koala73/worldmonitor@7d06c8633d (2026-08-21).
Data as JSON: /api/errors/576fd1a5157f69bc.
Report an issue: GitHub.
Appendix: source
Thrown at cli/src/core.mjs:206
let end = url.length;
while (end > 0 && url.charCodeAt(end - 1) === 47) end--;
return url.slice(0, end);
}
function baseHeaders(apiKey) {
const headers = { 'user-agent': USER_AGENT };
if (apiKey) headers[API_KEY_HEADER] = apiKey;
return headers;
}
// Tool/query arguments: an explicit --args JSON object wins; otherwise the
// collected --key value params, with bare boolean flags kept as true.
function collectArgs(parsed) {
if (parsed.options.args !== undefined) {
try {
return JSON.parse(parsed.options.args);
} catch (err) {
throw new UsageError(`--args must be valid JSON: ${err.message}`);
}
}
const args = {};
for (const [k, v] of Object.entries(parsed.params)) args[k] = v === true ? true : String(v);
return args;
}
function mcpPlan(method, rpcParams, options, config, extra = {}) {
const mcpUrl = options.mcpUrl || config.mcpUrl || DEFAULT_MCP_URL;
const apiKey = options.apiKey || config.apiKey;
const rpc = { jsonrpc: '2.0', id: 1, method };
if (rpcParams !== undefined) rpc.params = rpcParams;
return {
kind: 'mcp',
url: mcpUrl,
method: 'POST',
headers: {
...baseHeaders(apiKey),View on GitHub (pinned to 7d06c8633d)