paperclipai/paperclip · error · Error

Failed to parse JSON at ${filePath}: ${err instanceof Error

Error message

Failed to parse JSON at ${filePath}: ${err instanceof Error ? err.message : String(err)}

What it means

Thrown by parseJson() in cli/src/client/context.ts when the CLI context file (selected via --context or the default ~/.paperclip/context.json) exists but is not valid JSON. The raw JSON.parse error message is appended so the user can locate the syntax fault. The context file holds CLI profiles (apiBase, apiKey env refs, companyId, persona) and is written by `paperclipai context set`.

Source

Thrown at cli/src/client/context.ts:64

  if (process.env.PAPERCLIP_CONTEXT) return path.resolve(process.env.PAPERCLIP_CONTEXT);
  return findContextFileFromAncestors(process.cwd()) ?? resolveDefaultContextPath();
}

export function defaultClientContext(): ClientContext {
  return {
    version: 2,
    currentProfile: DEFAULT_PROFILE,
    profiles: {
      [DEFAULT_PROFILE]: {},
    },
  };
}

function parseJson(filePath: string): unknown {
  try {
    return JSON.parse(fs.readFileSync(filePath, "utf-8"));
  } catch (err) {
    throw new Error(`Failed to parse JSON at ${filePath}: ${err instanceof Error ? err.message : String(err)}`);
  }
}

function toStringOrUndefined(value: unknown): string | undefined {
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
}

function normalizeProfile(value: unknown): ClientContextProfile {
  if (typeof value !== "object" || value === null || Array.isArray(value)) return {};
  const profile = value as Record<string, unknown>;
  const persona = profile.persona === "board" || profile.persona === "agent"
    ? profile.persona
    : undefined;

  return {
    apiBase: toStringOrUndefined(profile.apiBase),
    companyId: toStringOrUndefined(profile.companyId),
    persona,

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Open the path from the error message and fix the JSON syntax error cited.
  2. Reset to a valid empty profile: write `{ "version": 2, "currentProfile": "default", "profiles": { "default": {} } }`.
  3. Re-establish settings via `paperclipai context set` instead of hand-editing.
  4. If unsure which profile is corrupt, back up the file and recreate it profile by profile.

Example fix

// before — ~/.paperclip/context.json
{
  // my settings
  "version": 2,
  currentProfile: "default",
  ...
}

// after
{
  "version": 2,
  "currentProfile": "default",
  "profiles": { "default": {} }
}
Defensive patterns

Strategy: validation

Validate before calling

import fs from 'node:fs';
function tryLoadContext(path: string): unknown | null {
  if (!fs.existsSync(path)) return null;
  const text = fs.readFileSync(path, 'utf-8');
  try { return JSON.parse(text); }
  catch { console.warn(`Context file ${path} is corrupt; ignoring. Fix or run: paperclipai context set`); return null; }
}

Type guard

function isContextFile(v: unknown): v is { version: number; currentProfile: string; profiles: Record<string, unknown> } {
  return typeof v === 'object' && v !== null &&
    typeof (v as any).version === 'number' &&
    typeof (v as any).currentProfile === 'string' &&
    typeof (v as any).profiles === 'object';
}

Try / catch

try {
  readContext(contextPath);
} catch (err) {
  const msg = err instanceof Error ? err.message : String(err);
  if (msg.startsWith('Failed to parse JSON at')) {
    console.error(`Context file corrupt: ${msg}. Back it up and reset with: paperclipai context set`);
    process.exit(2);
  }
  throw err;
}

Prevention

When it happens

Trigger: Running any CLI command after the context file got corrupted: hand-edited and saved with a trailing comma / unquoted key / comment, partially written due to a crash mid-write, or overwritten by another tool. The file exists (so readFileSync succeeds) but JSON.parse throws.

Common situations: Manual edit of ~/.paperclip/context.json. A prior `paperclipai context set` was killed mid-write. Merge conflict left conflict markers in the file. JSON5-style syntax (comments, unquoted keys) mistakenly used.

Understand the failure class

Related errors


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