kysely-org / kysely

A type-safe typescript SQL query builder
https://kysely.dev
MIT License
9.81k stars 249 forks source link

QueryCompilerError: Could not serialize value causes Kysely instance to fail later #1028

Closed mdnorman closed 2 weeks ago

mdnorman commented 4 weeks ago

The following code will cause an error and then break the DB connection for further updates.

const DB = new Kysely<Database>(...);

const someIds = [undefined]; // oops!
const otherId = 1234;

try {
  await db.selectFrom("a").where("id", "in", someIds).execute(),
} catch(e) {
  // e is "QueryCompilerError: Could not serialize value" because of the undefined

  await db.updateTable("b").where("id", "=", otherId).set({ status: "error" }).execute();
  // line above throws another error because the generated SQL is 
  // "(update "b" set "status" = :0 where "id" = :1)"
  // notice the parentheses around the generated SQL
}

I confirmed that restarting the service and running the update call works fine because the generated SQL does not have the surrounding parentheses. I confirmed the presence of the parentheses with query.compile().sql.

koskimas commented 4 weeks ago

Ouch, thanks for opening the issue! We don't clear the OperationNodeVisitor.nodeStack at the beginning of compilation. The stack is left behind from that interrupted compilation.

But that query shouldn't pass typescript checks. The type of the array is undefined[]. Even if the type was (string | undefined)[] Kysely wouldn't accept it. Are you using some extremely loose typescript settings? Strict mode is needed for Kysely types to function properly.

https://kyse.link/C43WH

mdnorman commented 4 weeks ago

Yep, you're absolutely right about the types. This was a simple repro to demonstrate the problem, but in the real case, the undefined sneakily got in there from a much earlier part of the pipeline.