{"record":{"id":"341abb505e3da984","repo":"nanocoai/nanoclaw","slug":"flag-must-be-valid-json","errorCode":null,"errorMessage":"${flag} must be valid JSON","messagePattern":"(.+?) must be valid JSON","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cli/crud.ts","lineNumber":439,"sourceCode":"    switch (def.type) {\n      case 'number': {\n        const n = Number(v);\n        if (Number.isNaN(n)) throw new Error(`${flag} must be a number, got \"${v}\"`);\n        out[def.name] = n;\n        break;\n      }\n      case 'boolean': {\n        if (v === true || v === 'true' || v === '1') out[def.name] = true;\n        else if (v === false || v === 'false' || v === '0') out[def.name] = false;\n        else throw new Error(`${flag} must be true or false, got \"${v}\"`);\n        break;\n      }\n      case 'json': {\n        if (typeof v === 'string') {\n          try {\n            out[def.name] = JSON.parse(v);\n          } catch (err) {\n            throw new Error(`${flag} must be valid JSON`, { cause: err });\n          }\n        }\n        break;\n      }\n      case 'string':\n        out[def.name] = String(v);\n        break;\n    }\n    if (def.enum && !def.enum.includes(String(out[def.name]))) {\n      throw new Error(`${flag} must be one of: ${def.enum.join(', ')}`);\n    }\n  }\n  return out;\n}\n\n// ---------------------------------------------------------------------------\n// registerResource\n// ---------------------------------------------------------------------------","sourceCodeStart":421,"sourceCodeEnd":457,"githubUrl":"https://github.com/nanocoai/nanoclaw/blob/294ef2aee85218b23ad30eda9dfe10e590b54a8c/src/cli/crud.ts#L421-L457","documentation":"A flag declared with `type: 'json'` must parse as JSON when passed as a string. JSON.parse threw, and the error is re-thrown with the parse failure as `cause` so the exact syntax problem is preserved.","triggerScenarios":"Passing unquoted or shell-mangled JSON (`--config {a:1}` — unquoted keys are invalid JSON); single-quote wrapping stripped by the shell leaving bare braces that trigger globbing or splitting; trailing commas; passing a filename instead of file contents; passing YAML instead of JSON.","commonSituations":"Shell quoting mistakes with nested quotes (`--payload \"{\\\"k\\\":1}\"` done wrong); agents emitting pretty-printed multi-line JSON the shell splits on spaces; forgetting that JSON requires double-quoted strings.","solutions":["Wrap the JSON in single quotes so the shell passes it verbatim: `--payload '{\"key\": 1}'`","Validate the payload with `echo '<json>' | jq .` before running the command","Use the `--flag=value` form to avoid tokenization issues","Inspect `error.cause` for the precise JSON.parse position"],"exampleFix":"# before\nncl groups config update --id g1 --mounts {/data:/data}\n# Error: --mounts must be valid JSON\n\n# after\nncl groups config update --id g1 --mounts '{\"/data\":\"/data\"}'","handlingStrategy":"validation","validationCode":"if (typeof v === 'string') { try { JSON.parse(v); } catch { throw new Error('payload is not valid JSON — check quoting'); } }","typeGuard":"function isValidJsonString(v: string): boolean {\n  try { JSON.parse(v); return true; } catch { return false; }\n}","tryCatchPattern":"catch (e) { if (e instanceof Error && /must be valid JSON/.test(e.message)) { /* inspect e.cause for parse position, fix quoting */ } else throw e; }","preventionTips":["Wrap JSON payloads in single quotes at the shell","Pipe through `jq .` as a pre-flight check","Use --flag='...' syntax to avoid word splitting"],"tags":["cli","argument-validation","json","shell-quoting"],"backgroundTag":"invalid-json-payload","analyzedSha":"294ef2aee85218b23ad30eda9dfe10e590b54a8c","analyzedAt":"2026-08-28T13:59:10.357Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}