Bug description
When schema.prisma contains a single byte that is not valid UTF-8 — for example a lone Windows-1252 0x97 (an em-dash in CP-1252) inside a comment, the kind of byte a text editor on Windows can silently write — the schema engine cannot read the datamodel file and panics:
[schema-engine/cli/src/main.rs:222:21] Error reading datamodel file `/path/to/schema.prisma`: stream did not contain valid UTF-8
But prisma migrate deploy does not fail: it prints the normal banner, applies nothing, and exits with code 0. Unless DEBUG=prisma:* is set, nothing indicates that anything went wrong, so CI and deploy pipelines treat the run as successful.
prisma db push behaves the same way (exits 0, no changes made). prisma validate and prisma format also exit 0 — they read the schema through a different (WASM) path that tolerates the invalid byte, so they don't catch it either. format actually rewrites the file, replacing the byte with U+FFFD, without any warning.
Expected behavior
A non-zero exit code and a visible error on stderr, without requiring DEBUG.
Actual behavior
Without DEBUG (full output from the repro below):
$ npx prisma migrate deploy
Prisma schema loaded from prisma/schema.prisma
Datasource "db": SQLite database "dev.db" at "file:./dev.db"
1 migration found in prisma/migrations
$ echo $?
0
No migration is applied. The engine panic is only visible with DEBUG=prisma:*:
$ DEBUG='prisma:*' npx prisma migrate deploy
prisma:schemaEngine:rpc starting Schema engine with binary: .../schema-engine-windows.exe
prisma:schemaEngine:rpc SENDING RPC CALL {"id":1,"jsonrpc":"2.0","method":"applyMigrations",...}
prisma:schemaEngine:stderr {"level":"ERROR","fields":{"message":"[schema-engine/cli/src/main.rs:222:21] Error reading datamodel file `.../schema.prisma`: stream did not contain valid UTF-8","is_panic":true,...}}
$ echo $?
0
From a production incident on a Linux runner (Debian, schema-engine-debian-openssl-3.0.x), where the CLI printed an error with DEBUG enabled but still exited 0:
$ DEBUG='prisma:*' prisma migrate deploy
prisma:schemaEngine:stderr {...,"level":"ERROR","fields":{"message":"[schema-engine/cli/src/main.rs:222:21] Error reading datamodel file `/path/schema.prisma`: stream did not contain valid UTF-8","is_panic":true,...}}
Error: Error in Schema engine.
Reason: [schema-engine/cli/src/main.rs:222:21] Error reading datamodel file `...`: stream did not contain valid UTF-8
$ echo $?
0
Without DEBUG, the same command printed only 44 migrations found in prisma/migrations and exited 0.
Minimal reproduction
mkdir prisma-repro && cd prisma-repro
npm init -y
npm install --no-save prisma@6.19.3
Create prisma/schema.prisma containing exactly one invalid byte. Write it with Node so the raw byte survives (editors may silently re-encode it):
// make-schema.js
const fs = require('fs')
fs.writeFileSync(
'prisma/schema.prisma',
Buffer.concat([
Buffer.from('generator client {\n provider = "prisma-client-js"\n}\n\ndatasource db {\n provider = "sqlite"\n url = "file:./dev.db"\n}\n\n// dash: ', 'utf8'),
Buffer.from([0x97]), // lone Windows-1252 em-dash byte
Buffer.from('\n\nmodel T {\n id Int @id\n}\n', 'utf8'),
]),
)
Add one trivial migration:
mkdir -p prisma/migrations/20260101000000_init
printf 'provider = "sqlite"\n' > prisma/migrations/migration_lock.toml
printf 'CREATE TABLE "T" ("id" INTEGER PRIMARY KEY);\n' > prisma/migrations/20260101000000_init/migration.sql
Results:
| Command |
Output |
Exit code |
npx prisma migrate deploy |
1 migration found in prisma/migrations, migration not applied |
0 |
npx prisma migrate deploy with DEBUG=prisma:* |
engine panics: Error reading datamodel file ...: stream did not contain valid UTF-8 |
0 |
npx prisma db push |
prints the datasource line, then stops silently |
0 |
npx prisma validate |
The schema at prisma/schema.prisma is valid |
0 |
npx prisma format |
Formatted prisma/schema.prisma — silently rewrites the byte to U+FFFD |
0 |
Control: replacing the single 0x97 byte with a valid UTF-8 em-dash (—, U+2014) — nothing else changed — makes migrate deploy apply the migration normally (Applying migration 20260101000000_init … All migrations have been successfully applied) and exit 0. The single byte is the only variable.
Environment
- Prisma
6.19.3
- Schema Engine:
schema-engine-cli c2990dca591cba766e3b7ef5d9e8a84796e47ab7
- Reproduced on:
- Linux (Debian,
schema-engine-debian-openssl-3.0.x), Node 20 / 24 — where this hit production
- Windows 11 x64 (
schema-engine-windows.exe), Node 24.13.0
- The repro uses SQLite; the failure happens while reading
schema.prisma itself, before any database work, so the provider should not matter.
Real-world impact
In our app a Windows-1252 byte ended up in a comment in schema.prisma. prisma migrate deploy in CI exited 0 with no error, so the pipeline stayed green while a production migration was silently skipped for ~23 hours before anyone noticed. Debugging was slow because prisma validate explicitly reports the schema as valid, and there is no error output without DEBUG.
Notes for triage
Bug description
When
schema.prismacontains a single byte that is not valid UTF-8 — for example a lone Windows-12520x97(an em-dash in CP-1252) inside a comment, the kind of byte a text editor on Windows can silently write — the schema engine cannot read the datamodel file and panics:But
prisma migrate deploydoes not fail: it prints the normal banner, applies nothing, and exits with code 0. UnlessDEBUG=prisma:*is set, nothing indicates that anything went wrong, so CI and deploy pipelines treat the run as successful.prisma db pushbehaves the same way (exits 0, no changes made).prisma validateandprisma formatalso exit 0 — they read the schema through a different (WASM) path that tolerates the invalid byte, so they don't catch it either.formatactually rewrites the file, replacing the byte with U+FFFD, without any warning.Expected behavior
A non-zero exit code and a visible error on stderr, without requiring DEBUG.
Actual behavior
Without DEBUG (full output from the repro below):
No migration is applied. The engine panic is only visible with
DEBUG=prisma:*:From a production incident on a Linux runner (Debian,
schema-engine-debian-openssl-3.0.x), where the CLI printed an error with DEBUG enabled but still exited 0:Without DEBUG, the same command printed only
44 migrations found in prisma/migrationsand exited 0.Minimal reproduction
Create
prisma/schema.prismacontaining exactly one invalid byte. Write it with Node so the raw byte survives (editors may silently re-encode it):Add one trivial migration:
Results:
npx prisma migrate deploy1 migration found in prisma/migrations, migration not appliednpx prisma migrate deploywithDEBUG=prisma:*Error reading datamodel file ...: stream did not contain valid UTF-8npx prisma db pushnpx prisma validateThe schema at prisma/schema.prisma is validnpx prisma formatFormatted prisma/schema.prisma— silently rewrites the byte to U+FFFDControl: replacing the single
0x97byte with a valid UTF-8 em-dash (—, U+2014) — nothing else changed — makesmigrate deployapply the migration normally (Applying migration 20260101000000_init…All migrations have been successfully applied) and exit 0. The single byte is the only variable.Environment
6.19.3schema-engine-cli c2990dca591cba766e3b7ef5d9e8a84796e47ab7schema-engine-debian-openssl-3.0.x), Node 20 / 24 — where this hit productionschema-engine-windows.exe), Node 24.13.0schema.prismaitself, before any database work, so the provider should not matter.Real-world impact
In our app a Windows-1252 byte ended up in a comment in
schema.prisma.prisma migrate deployin CI exited 0 with no error, so the pipeline stayed green while a production migration was silently skipped for ~23 hours before anyone noticed. Debugging was slow becauseprisma validateexplicitly reports the schema as valid, and there is no error output without DEBUG.Notes for triage
applyMigrations(andschemaPushfordb push); from the DEBUG log it looks like the CLI treats the engine process dying as a successful no-op instead of a failure.prisma validateandprisma formatuse the WASM schema parser, which lossily accepts the invalid byte, so two codepaths in the same CLI disagree about whether the schema file is readable at all.prisma migrate resetalways exits with0, needs to exit with1on errors #9786 was the same class of exit-code bug formigrate reset; Error: Error in migration engine. Reason: [migration-engine\cli\src/main.rs:68:41] calledResult::unwrap()on anErrvalue: Custom { kind: InvalidData, error: "stream did not contain valid UTF-8" } #5614 (closed 2022, Prisma 2.16) is the same underlying engine read failure — back then it surfaced as a loud crash rather than a silent success.