{"record":{"id":"dca235d485dc3933","repo":"Yeachan-Heo/oh-my-codex","slug":"invalid-input-json-error-instanceof-error-e","errorCode":null,"errorMessage":"Invalid --input JSON: ${error instanceof Error ? error.message : String(error)}","messagePattern":"Invalid --input JSON: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cli/mcp-parity.ts","lineNumber":84,"sourceCode":"    descriptor.title,\n    \"\",\n    \"Available tools:\",\n    toolLines,\n    \"\",\n    \"Examples:\",\n    `  omx ${descriptor.commandName} ${descriptor.tools[0]?.name ?? \"<tool>\"} --input '{}' --json`,\n  ].join(\"\\n\");\n}\n\nfunction parseInputJson(raw: string): Record<string, unknown> {\n  try {\n    const parsed = JSON.parse(raw);\n    if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n      throw new Error(\"input JSON must decode to an object\");\n    }\n    return parsed as Record<string, unknown>;\n  } catch (error) {\n    throw new Error(\n      `Invalid --input JSON: ${error instanceof Error ? error.message : String(error)}`,\n    );\n  }\n}\n\nexport function parseMcpCliArgs(args: string[]): ParsedMcpCliArgs {\n  if (args.length === 0 || args[0] === \"--help\" || args[0] === \"-h\" || args[0] === \"help\") {\n    return { toolName: null, input: {}, json: false, help: true };\n  }\n\n  const [toolName, ...rest] = args;\n  let input: Record<string, unknown> = {};\n  let json = false;\n\n  for (let i = 0; i < rest.length; i += 1) {\n    const token = rest[i];\n    if (token === \"--json\") {\n      json = true;","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/cli/mcp-parity.ts#L66-L102","documentation":"parseInputJson wraps JSON.parse of the --input value for the MCP parity CLI. It rejects values that are not JSON objects (arrays, scalars, null are invalid) and re-wraps any parse failure as `Invalid --input JSON: <reason>`.","triggerScenarios":"Passing --input '[1,2]' (array), --input '\"x\"' or --input 'null' (non-object), or malformed JSON like --input '{a:1}' (unquoted keys) or a shell-mangled payload to the mcp parity command.","commonSituations":"Unquoted shell strings losing or garbling quotes; single vs double quote confusion in bash/zsh; JSON produced by a tool that emits a top-level array; trailing commas; Windows cmd escaping issues.","solutions":["Pass the JSON single-quoted in shell and use double quotes inside: --input '{\"key\":\"value\"}'","Ensure the top-level value is an object {} not an array or scalar","Validate with a linter or `echo '<json>' | jq type` expecting 'object' before invoking","Use a file and command substitution if the payload is large: --input \"$(cat input.json)\""],"exampleFix":"# before\nmycli mcp-tool run --input {\"key\":\"value\"}  # shell strips quotes -> invalid JSON\n\n# after\nmycli mcp-tool run --input '{\"key\":\"value\"}'","handlingStrategy":"validation","validationCode":"function parseSafe(raw: string): Record<string, unknown> {\n  const v = JSON.parse(raw); // throws SyntaxError on bad JSON\n  if (!v || typeof v !== 'object' || Array.isArray(v)) throw new Error('not an object');\n  return v as Record<string, unknown>;\n}\nconst input = parseSafe(payload); // validate before invoking CLI","typeGuard":"function isJsonObject(v: unknown): v is Record<string, unknown> {\n  return typeof v === 'object' && v !== null && !Array.isArray(v);\n}","tryCatchPattern":"try { await run(tool, input); }\ncatch (e) { if (/Invalid --input JSON/.test(String(e))) { console.error('Fix JSON quoting/shape'); process.exit(2); } throw e; }","preventionTips":["Single-quote the JSON in shell, double quotes inside","Pipe through `jq -e type==\"object\"` to pre-validate"],"tags":["cli","json","argument-parsing","shell-escaping"],"backgroundTag":"invalid-json-input","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}