isDbError() does not work
abegehr opened this issue · 5 comments
Astro Info
Astro v4.16.10
Node v22.6.0
System macOS (arm64)
Package Manager pnpm
Output server
Adapter @astrojs/vercel/serverless
Integrations @astrojs/tailwind
@astrojs/svelte
astro:db
@astrojs/db/file-url
If this issue only occurs in one browser, which browser is a problem?
No response
Describe the Bug
isDbError(err)
is false, even though the error is a LibsqlError SQLITE_CONSTRAINT_UNIQUE
thrown from db.insert
function in an Astro action.
try {
const user = await db.insert(User).values({ name }).returning().get(); // * throws LibsqlError `SQLITE_CONSTRAINT_UNIQUE` when user with name already exists.
return user;
} catch (err) {
if (isDbError(err)) {
console.warn("LibsqlError thrown:", err); // ! this never get's called, since `isDbError(err)` doesn't seem to work
} else {
console.error("Error thrown:", err);
}
}
Notice: the StackBlitz repro works only locally, since StackBlitz doesn't support Astro.clientAddress: #6451 (comment)
What's the expected result?
I would expect to be able to identify Libsql errors thrown from inserting into db with astro.
Link to Minimal Reproducible Example
https://stackblitz.com/edit/github-ofpscu-cwqc8l?file=src%2Factions%2Findex.ts
Participation
- I am willing to submit a pull request for this issue.
Repo with repro: https://github.com/abegehr/astro-issue-12400-repro (since StackBlitz doesn't support Astro.clientAddress)
To try it out, clone the repro repo, run npm i
, and npm run dev
. Then click the "Run Action"-button, which will try to insert a user with name=="test" into the database, which will fail uniqueness constraint, since that username is already seeded => Error:
createUser() test
Error thrown: Error: UNIQUE constraint failed: User.name
at Object.next (/Users/anton/local/repos/astro-issue-12400-repro/node_modules/libsql/index.js:335:20)
at Statement.all (/Users/anton/local/repos/astro-issue-12400-repro/node_modules/libsql/index.js:360:16)
at executeStmt (file:///Users/anton/local/repos/astro-issue-12400-repro/node_modules/@libsql/client/lib-esm/sqlite3.js:261:34)
at Sqlite3Client.execute (file:///Users/anton/local/repos/astro-issue-12400-repro/node_modules/@libsql/client/lib-esm/sqlite3.js:79:16)
at LibSQLPreparedQuery.values (file:///Users/anton/local/repos/astro-issue-12400-repro/node_modules/drizzle-orm/libsql/session.js:170:59)
at LibSQLPreparedQuery.get (file:///Users/anton/local/repos/astro-issue-12400-repro/node_modules/drizzle-orm/libsql/session.js:143:29)
at QueryPromise.get (file:///Users/anton/local/repos/astro-issue-12400-repro/node_modules/drizzle-orm/sqlite-core/query-builders/insert.js:148:28)
at handler (/Users/anton/local/repos/astro-issue-12400-repro/src/actions/index.ts:15:117)
at eval (/Users/anton/local/repos/astro-issue-12400-repro/node_modules/astro/dist/actions/runtime/virtual/server.js:68:18)
at async Module.callSafely (/Users/anton/local/repos/astro-issue-12400-repro/node_modules/astro/dist/actions/runtime/virtual/shared.js:112:18) {
rawCode: 2067,
code: 'SQLITE_CONSTRAINT_UNIQUE',
libsqlError: true
}
However, the catch condition will not identify an LibsqlError with isDbError(). I also tried err instance LibsqlError
directly, which also yields false. Therefore doesn't seem to be a way to identify a Libsql/Db-Error.
I've implemented a work-around guard for this:
export function isLibsqlError(err: unknown): err is LibsqlError {
if (!err || !(err instanceof Error)) return false;
const value = err as LibsqlError;
return (
typeof value.code === "string" &&
(value.rawCode === undefined || typeof value.rawCode === "number")
);
}
I can reproduce it locally.