{"record":{"id":"576fd1a5157f69bc","repo":"koala73/worldmonitor","slug":"args-must-be-valid-json-err-message","errorCode":null,"errorMessage":"--args must be valid JSON: ${err.message}","messagePattern":"--args must be valid JSON: (.+?)","errorType":"exception","errorClass":"UsageError","httpStatus":null,"severity":"error","filePath":"cli/src/core.mjs","lineNumber":204,"sourceCode":"\nfunction trimTrailingSlash(url) {\n  return url.replace(/\\/+$/, '');\n}\n\nfunction baseHeaders(apiKey) {\n  const headers = { 'user-agent': USER_AGENT };\n  if (apiKey) headers[API_KEY_HEADER] = apiKey;\n  return headers;\n}\n\n// Tool/query arguments: an explicit --args JSON object wins; otherwise the\n// collected --key value params, with bare boolean flags kept as true.\nfunction collectArgs(parsed) {\n  if (parsed.options.args !== undefined) {\n    try {\n      return JSON.parse(parsed.options.args);\n    } catch (err) {\n      throw new UsageError(`--args must be valid JSON: ${err.message}`);\n    }\n  }\n  const args = {};\n  for (const [k, v] of Object.entries(parsed.params)) args[k] = v === true ? true : String(v);\n  return args;\n}\n\nfunction mcpPlan(method, rpcParams, options, config, extra = {}) {\n  const mcpUrl = options.mcpUrl || config.mcpUrl || DEFAULT_MCP_URL;\n  const apiKey = options.apiKey || config.apiKey;\n  const rpc = { jsonrpc: '2.0', id: 1, method };\n  if (rpcParams !== undefined) rpc.params = rpcParams;\n  return {\n    kind: 'mcp',\n    url: mcpUrl,\n    method: 'POST',\n    headers: {\n      ...baseHeaders(apiKey),","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/koala73/worldmonitor/blob/eeab0a219fce0f02a00603b532dbae9041b934ac/cli/src/core.mjs#L186-L222","documentation":"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.","triggerScenarios":"--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.","commonSituations":"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.","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"],"exampleFix":"# before\nworldmonitor call get_country_risk --args \"{country_code: 'IR',}\"   # UsageError: --args must be valid JSON\n\n# after\nworldmonitor call get_country_risk --args '{\"country_code\":\"IR\"}'\n# or skip JSON entirely\nworldmonitor call get_country_risk --country_code IR","handlingStrategy":"validation","validationCode":"// Validate --args before spawning the CLI\nfunction parseCliArgs(json) {\n  try { return { ok: true, value: JSON.parse(json) }; }\n  catch (e) { return { ok: false, error: e.message }; }\n}\nconst check = parseCliArgs(argsJson);\nif (!check.ok) throw new Error(`--args is not valid JSON: ${check.error}`);","typeGuard":"function isJsonObject(v: unknown): v is Record<string, unknown> {\n  return typeof v === 'object' && v !== null && !Array.isArray(v);\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["cli","json","shell-quoting","usage"],"backgroundTag":"invalid-json-input","analyzedSha":"eeab0a219fce0f02a00603b532dbae9041b934ac","analyzedAt":"2026-08-21T16:51:25.751Z","schemaVersion":2},"datasetVersion":"2026-08-23T16:17:53.355Z"}