paperclipai/paperclip · error · Error

Invalid ${name} JSON: ${err instanceof Error ? err.message :

Error message

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

What it means

Catch-all thrown by parseJsonObject() in approval.ts for any error raised while parsing/validating an approval command's JSON option. It wraps JSON.parse SyntaxErrors (malformed JSON) AND the inner 'must be a JSON object' throw from [11]. The interpolated err.message tells you which sub-fault occurred.

Source

Thrown at cli/src/commands/client/approval.ts:258

      }),
  );
}

function parseCsv(value: string | undefined): string[] | undefined {
  if (!value) return undefined;
  const rows = value.split(",").map((v) => v.trim()).filter(Boolean);
  return rows.length > 0 ? rows : undefined;
}

function parseJsonObject(value: string, name: string): Record<string, unknown> {
  try {
    const parsed = JSON.parse(value) as unknown;
    if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
      throw new Error(`${name} must be a JSON object`);
    }
    return parsed as Record<string, unknown>;
  } catch (err) {
    throw new Error(`Invalid ${name} JSON: ${err instanceof Error ? err.message : String(err)}`);
  }
}

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Read the appended err.message: if it says 'Unexpected token', fix the JSON syntax; if it says 'must be a JSON object', wrap the value in {}.
  2. Validate with jq before passing: `--<name> "$(jq -c . input.json)"`.
  3. Avoid shell-quoting pitfalls by reading from a file if the JSON is non-trivial.

Example fix

// before
paperclipai approval ... --metadata {key:val}
// after
paperclipai approval ... --metadata '{"key":"val"}'
Defensive patterns

Strategy: validation

Validate before calling

function parseJsonObjectSafe(value: string, name: string): Record<string, unknown> {
  let parsed: unknown;
  try { parsed = JSON.parse(value); }
  catch (err) { throw new Error(`${name} is not valid JSON: ${err instanceof Error ? err.message : String(err)}`); }
  if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
    throw new Error(`${name} must be a JSON object`);
  }
  return parsed as Record<string, unknown>;
}

Type guard

function isPlainObject(v: unknown): v is Record<string, unknown> {
  return typeof v === 'object' && v !== null && !Array.isArray(v);
}

Try / catch

try { parseJsonObject(opts.metadata, 'metadata'); }
catch (err) {
  const msg = err instanceof Error ? err.message : '';
  if (msg.startsWith('Invalid metadata JSON:')) {
    console.error(msg); // contains the underlying cause
    process.exit(2);
  }
  throw err;
}

Prevention

When it happens

Trigger: (a) --<name> value is malformed JSON (unbalanced braces, trailing comma, unquoted keys) → JSON.parse throws SyntaxError. (b) Valid JSON but not an object → the inner [11] throw is caught and rewrapped here as `Invalid <name> JSON: <name> must be a JSON object`.

Common situations: Hand-typing JSON on the command line (missing quotes, single quotes instead of double, trailing commas). Passing a YAML-ish value. Passing a JSON array where an object is required.

Related errors


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