prisma/prisma · error · Error
${manifestPath}: not valid JSON (${error instanceof Error ?
Error message
${manifestPath}: not valid JSON (${error instanceof Error ? error.message : String(error)}) What it means
Thrown by the 0.16→0.17 extension-upgrade codemod (strip-sha256-hash-prefixes) when it locates a `migration.json` on disk and `JSON.parse(raw)` throws. The codemod walks the project tree for migration packages (a `migration.json` paired with a sibling `ops.json`) to strip the legacy `sha256:` hash prefix and recompute each manifest's `migrationHash`; before it can recompute it must parse the manifest, so a structurally-invalid file aborts the whole run. The trailing parenthesised message is Node's native JSON parse error, naming the position of the bad token.
Source
Thrown at skills/extension-author/prisma-next-extension-upgrade/upgrades/0.16-to-0.17/strip-sha256-hash-prefixes.ts:251
return { path, status: 'already-clean' };
}
if (!dryRun) await writeFile(path, after, 'utf-8');
return { path, status: dryRun ? 'needs-fix' : 'fixed' };
}
async function processSibling(path: string): Promise<Result> {
const raw = await readFile(path, 'utf-8');
return emit(path, raw, stripHashPrefixes(raw));
}
async function processPackage(manifestPath: string): Promise<Result[]> {
const raw = await readFile(manifestPath, 'utf-8');
let parsed: unknown;
try {
parsed = JSON.parse(raw);
} catch (error) {
throw new Error(
`${manifestPath}: not valid JSON (${error instanceof Error ? error.message : String(error)})`,
);
}
if (!isJsonObject(parsed)) {
return [{ path: manifestPath, status: 'already-clean' }]; // not a manifest object
}
const packageDir = dirname(manifestPath);
// A complete on-disk migration package pairs `migration.json` with a sibling
// `ops.json` (the operations the hash is computed over); without it we cannot
// recompute the hash, so this is not a package we should touch.
const opsPath = join(packageDir, 'ops.json');
let opsRaw: string;
try {
opsRaw = await readFile(opsPath, 'utf-8');
} catch {
return [{ path: manifestPath, status: 'skipped-no-ops' }];View on GitHub (pinned to 1243cdffbe)
Solutions
- Open the file at the path printed in the message and fix the JSON syntax error at the offset/position given in the parenthesised parse error.
- If the corruption is from a git merge conflict, resolve the conflict markers then re-run the codemod (it is idempotent).
- If the manifest is disposable, restore it from a clean checkout (`git checkout -- <path>`) or re-generate it with the migration authoring tooling, then re-run.
- Validate the file with a JSON linter (`pnpm exec tsx -e "JSON.parse(require('fs').readFileSync('<path>','utf8'))"`) before re-running.
Example fix
// before — migrations/0001_init/migration.json
{
"from": "sha256:8ee1e7ce...",
"to": "sha256:059f3f35...",
"providedInvariants": [], // <- trailing comma / comment breaks JSON.parse
}
// after
{
"from": "sha256:8ee1e7ce...",
"to": "sha256:059f3f35...",
"providedInvariants": []
} Defensive patterns
Strategy: try-catch
Validate before calling
import { readFile } from 'node:fs/promises';
// Pre-scan every migration.json / package.json before invoking the upgrade.
async function assertManifestsAreValidJson(paths: string[]): Promise<void> {
for (const manifestPath of paths) {
const raw = await readFile(manifestPath, 'utf-8');
try { JSON.parse(raw); }
catch (error) {
const msg = error instanceof Error ? error.message : String(error);
throw new Error(`Refusing to run upgrade: ${manifestPath} is not valid JSON (${msg})`);
}
}
} Try / catch
try {
await runUpgradeScripts(projectRoot);
} catch (error) {
if (error instanceof Error && error.message.includes(': not valid JSON (')) {
const offending = error.message.split(':')[0];
console.error(`Upgrade aborted: fix or regenerate ${offending}, then re-run.`);
process.exit(1);
}
throw error;
} Prevention
- Never hand-edit migration.json or package.json; regenerate them via the CLI so they stay valid JSON.
- Add a JSON linter or `git diff --check` to your pre-commit hook.
- Commit only tool-generated migration artifacts.
- Run `pnpm fixtures:check` before invoking upgrade scripts.
When it happens
Trigger: Running `pnpm exec tsx .../strip-sha256-hash-prefixes.ts` (with or without `--check`) from a project root where some `migration.json` cannot be parsed: a trailing comma, an unquoted key, a comment, a BOM, a truncated file, or literal merge-conflict markers (`<<<<<<<`) left in the bytes.
Common situations: An unresolved git merge/rebase conflict left conflict markers inside `migrations/<dir>/migration.json`; a previous codemod or editor write was interrupted mid-flush leaving a partial file; a hand-edited manifest with a JSON5-style trailing comma or `//` comment; a teammate committed a `.json5` renamed to `.json`.
Related errors
- ${manifestPath}: manifest is not a JSON object
- ${manifestPath}: manifest is missing a string `migrationHash
- ${path}: not valid JSON (${error instanceof Error ? error.me
- ${path}: not valid JSON (${error instanceof Error ? error.me
- ${filePath}: storage.types[${JSON.stringify(name)}] is neith
AI-assisted analysis of prisma/prisma@1243cdffbe (2026-08-01).
Data as JSON: /data/errors/970bf1dcbbce1093.json.
Report an issue: GitHub.