{"id":"3f5fddd46c7cfa76","repo":"prisma/prisma","slug":"path-not-valid-json-error-instanceof-error-3f5fdd","errorCode":null,"errorMessage":"${path}: not valid JSON (${error instanceof Error ? error.message : String(error)})","messagePattern":"(.+?): not valid JSON \\((.+?)\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"skills/upgrade/prisma-next-upgrade/upgrades/0.9-to-0.10/stamp-storage-types-kind.ts","lineNumber":319,"sourceCode":"  if (typeof value === 'object') {\n    const entries = Object.entries(value as Record<string, unknown>);\n    if (entries.length === 0) return '{}';\n    const lines = entries.map(\n      ([k, v]) => `${childIndent}${JSON.stringify(k)}: ${formatJson(v, indentLevel + 1)}`,\n    );\n    return `{\\n${lines.join(',\\n')}\\n${indent}}`;\n  }\n\n  throw new Error(`Unsupported value: ${typeof value}`);\n}\n\nasync function processFile(path: string): Promise<Result> {\n  const raw = await readFile(path, 'utf-8');\n  let parsed: unknown;\n  try {\n    parsed = JSON.parse(raw);\n  } catch (error) {\n    throw new Error(\n      `${path}: not valid JSON (${error instanceof Error ? error.message : String(error)})`,\n    );\n  }\n  const outcome = processContract(parsed, path);\n  if (outcome.transformed === null) {\n    return { path, status: 'already-clean', stamped: 0 };\n  }\n  const serialised = `${formatJson(outcome.transformed)}\\n`;\n  if (!dryRun) await writeFile(path, serialised, 'utf-8');\n  return { path, status: dryRun ? 'needs-fix' : 'fixed', stamped: outcome.stamped };\n}\n\nconst contracts = await findContractSnapshots(projectRoot);\nif (contracts.length === 0) {\n  console.error(`No start-contract.json / end-contract.json files found under ${projectRoot}.`);\n  process.exit(1);\n}\n","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/prisma/prisma/blob/1243cdffbec0506c595ac8fd5865fe258c336fa0/skills/upgrade/prisma-next-upgrade/upgrades/0.9-to-0.10/stamp-storage-types-kind.ts#L301-L337","documentation":"Thrown by the core 0.9→0.10 upgrade codemod (stamp-storage-types-kind) when `JSON.parse(raw)` fails on a `start-contract.json` or `end-contract.json` it discovered under a `migrations/` tree. Before stamping the `kind` discriminator the codemod must parse the snapshot; a structurally invalid file aborts the run. The parenthesised message is Node's native JSON parse error locating the bad token.","triggerScenarios":"Running the codemod against a `migrations/` tree containing a `start-contract.json`/`end-contract.json` that is not valid JSON: trailing comma, unquoted key, comment, BOM, truncation, or merge-conflict markers.","commonSituations":"Unresolved git merge/rebase conflict markers inside a committed contract snapshot; an interrupted CLI write left a truncated snapshot; a hand-edited snapshot with JSON5 syntax; a `.jsonc` accidentally committed as `.json`.","solutions":["Open the file at the reported path and fix the syntax error at the position given in the parenthesised parse message.","If corrupted by a merge conflict, resolve the markers and re-run (the codemod is idempotent).","If the snapshot is disposable, regenerate it via the migration authoring tooling or restore from git, then re-run.","Run with `--check` first to enumerate all affected files before applying edits."],"exampleFix":"// before — migrations/0001/start-contract.json\n{\n  \"storage\": {\n    \"types\": {\n      \"Embedding1536\": { \"codecId\": \"pg/vector@1\", ... },\n    }  // <- trailing comma breaks JSON.parse\n}\n\n// after\n{\n  \"storage\": {\n    \"types\": {\n      \"Embedding1536\": { \"codecId\": \"pg/vector@1\", ... }\n    }\n  }\n}","handlingStrategy":"try-catch","validationCode":"import { readFile } from 'node:fs/promises';\n\n// Pre-validate every start-/end-contract.json before running the stamp upgrade.\nasync function assertContractSnapshotsAreValidJson(paths: string[]): Promise<void> {\n  for (const path of paths) {\n    const raw = await readFile(path, 'utf-8');\n    try { JSON.parse(raw); }\n    catch (error) {\n      const msg = error instanceof Error ? error.message : String(error);\n      throw new Error(`Refusing to run upgrade: ${path} is not valid JSON (${msg})`);\n    }\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await runStampUpgrade(projectRoot);\n} catch (error) {\n  if (error instanceof Error && error.message.includes(': not valid JSON (')) {\n    const offending = error.message.split(':')[0];\n    console.error(`Stamp upgrade aborted: regenerate ${offending} via the CLI, then re-run.`);\n    process.exit(1);\n  }\n  throw error;\n}","preventionTips":["Treat contract snapshots as CLI-authored artifacts; never edit them by hand.","Re-emit snapshots via `pnpm build` / contract-space tooling after schema changes.","Re-generate snapshots rather than merging conflicting JSON during rebases.","Run `pnpm fixtures:check` before upgrade scripts."],"tags":["codemod","json","contract","upgrade","migration"],"analyzedSha":"1243cdffbec0506c595ac8fd5865fe258c336fa0","analyzedAt":"2026-08-01T19:42:02.087Z","schemaVersion":2}