tursodatabase / libsql

libSQL is a fork of SQLite that is both Open Source, and Open Contributions.
https://turso.tech/libsql
MIT License
9.54k stars 252 forks source link

sqlite "ConstraintViolation" reported as a "PROXY_ERROR" #1537

Open VdeVentura opened 2 months ago

VdeVentura commented 2 months ago

As mentioned in the title, following are 2 traces coming from turso's UI, it's very easy to reproduce:

Violating NOT NULL constraint

Error: PROXY_ERROR: error executing a request on the primary: NOT NULL constraint failed: User.id
    at window.drizzle (https://turso.tech/_next/static/chunks/7061-c994b6446462fd0a.js:1:28549)
    at async https://turso.tech/_next/static/chunks/74f8cf84.b675ca02858c4173.js:400:3481
    at async https://turso.tech/_next/static/chunks/74f8cf84.b675ca02858c4173.js:25:22415
    at async Promise.all (index 0)
    at async saveChanges (https://turso.tech/_next/static/chunks/74f8cf84.b675ca02858c4173.js:25:22362)
    at async https://turso.tech/_next/static/chunks/74f8cf84.b675ca02858c4173.js:144:7618

Violating UNIQUE constraint

PROXY_ERROR: error executing a request on the primary: UNIQUE constraint failed: User.email

This is a problem as it hurts error handling in apps.

haaawk commented 2 months ago

What language are you using on the client? Are you using embedded replicas or remote only? What is the exact problem with error handling? It seems that proxy error includes all the details of the problem, no?

VdeVentura commented 2 months ago

I'm using TS with Prisma, I could very well just assume that "PROXY_ERROR" is the same as a constraint violation, but it's highly unexpected considering that statement errors in libsql contain a SqliteError which is mapped to sqlite_error_code and the latter contains SQLITE_CONSTRAINT

see: https://github.com/tursodatabase/libsql/blob/2402249b5d3445646d5514b3d5e66915fb836d6e/libsql-server/src/hrana/stmt.rs#L261

MarinPostma commented 2 months ago

This is because the statement was proxied to the primary. We need to improve how errors are reported back to the replica, and then returned to the client.

VdeVentura commented 2 months ago

@MarinPostma: confirmed, I deleted the replica and started getting the expected error codes, however, I think there might still be something funky going on (it might even be on prisma's side, but from a high level look at the code, it sounds like it could be on libsql):

now I'm getting SQLITE_CONSTRAINT, which I can work with, but prisma is not supposed to return the libsql code; it's supposed to map it to their internal error codes (unique constraint for example). Looking at the specificity of the errors that prisma is intended to report, it looks difficult to map something as generic as SQLITE_CONSTRAINT to Unique constraint or Null constraintfor example.

Seems that prisma is expecting something along the lines of SQLITE_CONSTRAINT_UNIQUE or SQLITE_CONSTRAINT_NOTNULL which would be even better for error handling than just SQLITE_CONSTRAINT