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
- Open the path from the error message and fix the JSON syntax error cited.
- Reset to a valid empty profile: write `{ "version": 2, "currentProfile": "default", "profiles": { "default": {} } }`.
- Re-establish settings via `paperclipai context set` instead of hand-editing.
- 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
- Never hand-edit ~/.paperclip/context.json; use `paperclipai context set`.
- Commit a known-good context file in dotfiles so a corrupt one can be restored.
- Avoid JSON5 syntax (comments/trailing commas) in the context file.
- If scripting writes to it, write atomically (temp file + rename) to avoid partial writes.
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
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Company ID is required. Pass --company-id, set PAPERCLIP_COM
- --payload must be a JSON object
- ${name} must be a JSON object
- Invalid ${name} JSON: ${err instanceof Error ? err.message :
- Invalid --persona value. Use board or agent.
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/6b8c2f34dccc64dd.
Report an issue: GitHub.