Description
Hi!
I’ve set up a new site and would like to use Turso as my database provider. However, when I try accessing data from my site hosted on Vercel, I’m getting a 401 HTTP status code thrown from the @libsql/client
and I have no clue why. When I connect to the database locally, I simply cannot reproduce the issue.
I tried recreating the database, recreating the group, and tweaking the Drizzle configuration, but none of it seemed to work. I have no idea what’s throwing this exception and why the request from Vercel isn’t getting authorized properly.
If more information is necessary, I’d be more than happy to provide this!
Thanks in advance!
More details
Stacktrace
LibsqlError: SERVER_ERROR: Server returned HTTP status 401
at mapHranaError (file:///var/task/node_modules/.pnpm/@libsql+client@0.14.0/node_modules/@libsql/client/lib-esm/hrana.js:268:16)
at file:///var/task/node_modules/.pnpm/@libsql+client@0.14.0/node_modules/@libsql/client/lib-esm/http.js:76:23
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async LibSQLPreparedQuery.get (file:///var/task/node_modules/.pnpm/drizzle-orm@0.35.3_@libsql+client-wasm@0.14.0_@libsql+client@0.14.0_react@19.0.0-rc-cae764ce-_beykhe332nz34cv7xpk57h4rsy/node_modules/drizzle-orm/libsql/session.js:155:18)
at async login (file:///var/task/build/server/nodejs-eyJydW50aW1lIjoibm9kZWpzIn0/index.js:505:17)
at async file:///var/task/build/server/nodejs-eyJydW50aW1lIjoibm9kZWpzIn0/index.js:1955:20
at async Object.callRouteAction (/var/task/node_modules/.pnpm/@remix-run+server-runtime@2.13.1_typescript@5.6.3/node_modules/@remix-run/server-runtime/dist/data.js:36:16)
at async /var/task/node_modules/.pnpm/@remix-run+router@1.20.0/node_modules/@remix-run/router/dist/router.cjs.js:4719:19
at async callLoaderOrAction (/var/task/node_modules/.pnpm/@remix-run+router@1.20.0/node_modules/@remix-run/router/dist/router.cjs.js:4785:16)
at async Promise.all (index 2) {
code: 'SERVER_ERROR',
rawCode: undefined,
[cause]: HttpServerError: Server returned HTTP status 401
at errorFromResponse (file:///var/task/node_modules/.pnpm/@libsql+hrana-client@0.7.0/node_modules/@libsql/hrana-client/lib-esm/http/stream.js:352:16)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
status: 401
}
}
package.json
{
"name": "[REDACTED]",
"private": true,
"sideEffects": false,
"type": "module",
"scripts": {
"build": "remix vite:build",
"dev": "run-p dev:*",
"dev:app": "remix vite:dev",
"dev:turso": "turso dev --db-file './drizzle/db/data.db'",
"dev:drizzle": "drizzle-kit studio",
"lint": "eslint --cache --cache-location ./node_modules/.cache/eslint .",
"start": "remix-serve ./build/server/index.js",
"db:push": "drizzle-kit push",
"db:generate": "drizzle-kit generate",
"db:migrate": "dotenv -e .env -- tsx ./drizzle/migrate.ts",
"db:seed": "dotenv -e .env -- tsx ./drizzle/seed.ts",
"db:studio": "drizzle-kit studio",
"typecheck": "tsc",
"format": "prettier --check --cache .",
"prepare": "husky"
},
"dependencies": {
"@conform-to/react": "^1.2.2",
"@conform-to/zod": "^1.2.2",
"@epic-web/invariant": "^1.0.0",
"@epic-web/totp": "^2.0.0",
"@libsql/client": "^0.14.0",
"@paralleldrive/cuid2": "^2.2.2",
"@radix-ui/react-dialog": "^1.1.2",
"@radix-ui/react-dropdown-menu": "^2.1.2",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-popover": "^1.1.2",
"@radix-ui/react-select": "^2.1.2",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.3",
"@react-email/components": "^0.0.25",
"@remix-run/node": "^2.13.1",
"@remix-run/react": "^2.13.1",
"@remix-run/router": "^1.20.0",
"@remix-run/serve": "^2.13.1",
"@t3-oss/env-core": "^0.11.1",
"@vercel/remix": "^2.13.1",
"bcryptjs": "^2.4.3",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"cmdk": "^1.0.0",
"drizzle-orm": "^0.35.3",
"input-otp": "^1.2.4",
"isbot": "^5.1.17",
"lucide-react": "^0.453.0",
"react": "rc",
"react-dom": "rc",
"remix-themes": "^1.5.1",
"resend": "^4.0.0",
"sonner": "^1.5.0",
"spin-delay": "^2.0.1",
"tailwind-merge": "^2.5.4",
"tailwindcss-animate": "^1.0.7",
"zod": "^3.23.8"
},
"devDependencies": {
"@eslint/js": "^9.13.0",
"@faker-js/faker": "^9.0.3",
"@remix-run/dev": "^2.13.1",
"@total-typescript/tsconfig": "^1.0.4",
"@types/bcryptjs": "^2.4.6",
"@types/react": "npm:types-react@rc",
"@types/react-dom": "npm:types-react-dom@rc",
"autoprefixer": "^10.4.20",
"dotenv-cli": "^7.4.2",
"drizzle-kit": "^0.26.2",
"eslint": "^9.13.0",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.3",
"eslint-plugin-import-x": "^4.3.1",
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-perfectionist": "^3.9.1",
"eslint-plugin-react": "^7.37.2",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.14",
"globals": "^15.11.0",
"husky": "^9.1.6",
"lint-staged": "^15.2.10",
"npm-run-all": "^4.1.5",
"postcss": "^8.4.47",
"prettier": "^3.3.3",
"prettier-plugin-tailwindcss": "^0.6.8",
"tailwindcss": "^3.4.14",
"tsx": "^4.19.1",
"typescript": "^5.6.3",
"typescript-eslint": "^8.11.0",
"vite": "^5.4.10",
"vite-tsconfig-paths": "^5.0.1"
},
"overrides": {
"@types/react": "npm:types-react@rc",
"@types/react-dom": "npm:types-react-dom@rc"
},
"engines": {
"node": ">=20.0.0"
},
"packageManager": "pnpm@9.12.2",
"lint-staged": {
"*": "prettier --write --ignore-unknown"
}
}
app/db/index.ts
import { createClient } from "@libsql/client";
import { drizzle } from "drizzle-orm/libsql";
import { env } from "~/lib/env.server";
import * as schema from "./schema";
export const connection = createClient({
authToken: env.TURSO_AUTH_TOKEN,
url: env.TURSO_DATABASE_URL,
});
export const db = drizzle(connection, { schema });
app/routes/temp._index/route.tsx
import { json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
import { db } from "~/db";
export async function loader() {
const users = await db.query.user.findMany();
return json({ users });
}
export default function Route() {
const data = useLoaderData<typeof loader>();
return (
<div>
<h1>Users</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
drizzle.config.ts
import { defineConfig } from "drizzle-kit";
export default defineConfig({
dbCredentials: {
authToken: process.env.TURSO_AUTH_TOKEN || undefined,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
url: process.env.TURSO_DATABASE_URL!,
},
dialect: "turso",
out: "./drizzle/migrations",
schema: "./app/db/schema.ts",
});