Skip to content

prisma migrate deploy exits 0 without applying migrations when schema.prisma contains invalid UTF-8 #30198

Description

@wilanahattingh

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_initAll 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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions