{"record":{"id":"e2fbc0dbe8e18c76","repo":"paperclipai/paperclip","slug":"invalid-json-err-instanceof-error-err-message","errorCode":null,"errorMessage":"Invalid JSON: ${err instanceof Error ? err.message : String(err)}","messagePattern":"Invalid JSON: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cli/src/commands/client/project.ts","lineNumber":226,"sourceCode":"}\n\nfunction parseCsv(value: string | undefined): string[] | undefined {\n  if (value === undefined) return undefined;\n  return value.split(\",\").map((part) => part.trim()).filter(Boolean);\n}\n\nfunction parseNullableString(value: string | undefined): string | null | undefined {\n  if (value === undefined) return undefined;\n  return value.trim().toLowerCase() === \"null\" ? null : value;\n}\n\nfunction parseOptionalJson(value: string | undefined): unknown {\n  if (value === undefined) return undefined;\n  if (value.trim().toLowerCase() === \"null\") return null;\n  try {\n    return JSON.parse(value);\n  } catch (err) {\n    throw new Error(`Invalid JSON: ${err instanceof Error ? err.message : String(err)}`);\n  }\n}\n","sourceCodeStart":208,"sourceCodeEnd":229,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/cli/src/commands/client/project.ts#L208-L229","documentation":"`parseOptionalJson` converts a CLI string option into a JS value. It first maps the literal token `null` (case-insensitive) to `null`, then attempts `JSON.parse`. If parsing throws, the original parse error message is interpolated into a new Error and re-thrown. This wraps raw JSON.parse diagnostics so the user sees which option value failed. The function is used for options like metadata/JSON blobs passed on the command line.","triggerScenarios":"Passing a JSON-bearing option (e.g. `--metadata`) whose value is neither the literal `null` nor valid JSON — examples: unquoted object syntax the shell mangled, trailing commas, single-quoted JSON, or a value like `{}` that the shell stripped braces from.","commonSituations":"Shell quoting errors where `{\"a\":1}` loses its quotes and becomes `{a:1}`; copy-pasting JS object literals (single quotes, unquoted keys) instead of strict JSON; passing an empty string when `null` was intended.","solutions":["Pass strict JSON with proper shell quoting: `--metadata '{\"key\":\"value\"}'`","Use the literal token `null` (case-insensitive) when you mean an explicit null value","Validate the JSON with `echo '<value>' | jq .` before running the command to surface the exact syntax error"],"exampleFix":"# before\npaperclipai project create acme --metadata {key:val}\n# after\npaperclipai project create acme --metadata '{\"key\":\"val\"}'","handlingStrategy":"validation","validationCode":"// Validate JSON option strings before passing them through\nfunction safeParseOptionalJson(value: string | undefined): unknown {\n  if (value === undefined) return undefined;\n  if (value.trim().toLowerCase() === \"null\") return null;\n  try {\n    return JSON.parse(value);\n  } catch {\n    return undefined; // or surface a controlled error\n  }\n}\nconst parsed = safeParseOptionalJson(raw);","typeGuard":null,"tryCatchPattern":"try {\n  JSON.parse(raw);\n} catch (err) {\n  console.error(`--metadata is not valid JSON: ${err instanceof Error ? err.message : err}`);\n  process.exit(2);\n}","preventionTips":["Validate JSON-bearing args with `jq .` before running the command","Single-quote JSON on the shell to preserve quotes","Use the literal `null` token instead of empty strings for explicit null"],"tags":["cli","json","validation","parsing"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}