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
- 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
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
- 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
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
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- --payload must be a JSON object
- ${name} must be a JSON object
- Invalid ${name} JSON: ${err instanceof Error ? err.message :
- Invalid --name-override "${raw}". Use slug=name.
- Invalid --secret-value "${raw}". Use key=value.
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/e2fbc0dbe8e18c76.
Report an issue: GitHub.