paperclipai/paperclip · error · Error

Invalid JSON: ${err instanceof Error ? err.message : String(

Error message

Invalid JSON: ${err instanceof Error ? err.message : String(err)}

What it means

`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.

Source

Thrown at cli/src/commands/client/project.ts:226

}

function parseCsv(value: string | undefined): string[] | undefined {
  if (value === undefined) return undefined;
  return value.split(",").map((part) => part.trim()).filter(Boolean);
}

function parseNullableString(value: string | undefined): string | null | undefined {
  if (value === undefined) return undefined;
  return value.trim().toLowerCase() === "null" ? null : value;
}

function parseOptionalJson(value: string | undefined): unknown {
  if (value === undefined) return undefined;
  if (value.trim().toLowerCase() === "null") return null;
  try {
    return JSON.parse(value);
  } catch (err) {
    throw new Error(`Invalid JSON: ${err instanceof Error ? err.message : String(err)}`);
  }
}

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Pass strict JSON with proper shell quoting: `--metadata '{"key":"value"}'`
  2. Use the literal token `null` (case-insensitive) when you mean an explicit null value
  3. Validate the JSON with `echo '<value>' | jq .` before running the command to surface the exact syntax error

Example fix

# before
paperclipai project create acme --metadata {key:val}
# after
paperclipai project create acme --metadata '{"key":"val"}'
Defensive patterns

Strategy: validation

Validate before calling

// Validate JSON option strings before passing them through
function safeParseOptionalJson(value: string | undefined): unknown {
  if (value === undefined) return undefined;
  if (value.trim().toLowerCase() === "null") return null;
  try {
    return JSON.parse(value);
  } catch {
    return undefined; // or surface a controlled error
  }
}
const parsed = safeParseOptionalJson(raw);

Try / catch

try {
  JSON.parse(raw);
} catch (err) {
  console.error(`--metadata is not valid JSON: ${err instanceof Error ? err.message : err}`);
  process.exit(2);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Related errors


AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12). Data as JSON: /api/errors/e2fbc0dbe8e18c76. Report an issue: GitHub.