I deployed a simple first version of a Sveltekit project successfully. After that I wanted to log into a database every time the site is accessed. For this, I created a Postgres database and table using Neon, linking it to my project for all three environments (dev, preview, prod). Then as instructed in the Getting started -> SvelteKit section I added @vercel/postgres to my project and used its sql function to insert some entries.
On my local system, appending the POSTGRES_URL to my .env file and running vercel dev, everything works as expected and I can see the database filling.
However, deploying to vercel, it works less often that not. Most of the calls to Neon fail with an Unhandled Rejection: NeonDbError: Error connecting to database: fetch failed. I would say 80% of the time it fails with this error, 10% of the time it doesn’t but I’ve got no entry to DB, and the last 10% I’ve got one. I can’t tell any pattern to those errors.
I checked that the database’s environment variables do appear in the project settings automatically, and tried a couple times already to unlink / link the database to the project again.
Did I miss a step or a piece of knowledge?
I am unable to get guidance using that official example since the Github’s link is dead and its demo links to a Prisma project :
Here is the full report of the crash (I have no error handling yet)
Unhandled Rejection: NeonDbError: Error connecting to database: fetch failed
at execute (file:///var/task/node_modules/@neondatabase/serverless/index.mjs:1545:25)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
at runNextTicks (node:internal/process/task_queues:64:3)
at process.processImmediate (node:internal/timers:454:9)
at process.callbackTrampoline (node:internal/async_hooks:130:17) {
severity: undefined,
code: undefined,
detail: undefined,
hint: undefined,
position: undefined,
internalPosition: undefined,
internalQuery: undefined,
where: undefined,
schema: undefined,
table: undefined,
column: undefined,
dataType: undefined,
constraint: undefined,
file: undefined,
line: undefined,
routine: undefined,
sourceError: TypeError: fetch failed
at node:internal/deps/undici/undici:13185:13
at processTicksAndRejections (node:internal/process/task_queues:95:5)
at runNextTicks (node:internal/process/task_queues:64:3)
at process.processImmediate (node:internal/timers:454:9)
at process.callbackTrampoline (node:internal/async_hooks:130:17)
at async execute (file:///var/task/node_modules/@neondatabase/serverless/index.mjs:1544:21) {
[cause]: ConnectTimeoutError: Connect Timeout Error (attempted addresses: ...:, ...:, ...:***)
at onConnectTimeout (node:internal/deps/undici/undici:2331:28)
at node:internal/deps/undici/undici:2283:50
at Immediate._onImmediate (node:internal/deps/undici/undici:2315:13)
at process.processImmediate (node:internal/timers:483:21)
at process.callbackTrampoline (node:internal/async_hooks:130:17) {
code: ‘UND_ERR_CONNECT_TIMEOUT’
}
}
}
Node.js process exited with exit status: 128. The logs above can help with debugging the issue.
Hey @pierremdl. You mentioned adding the environment variables to the .env file, but that wouldn’t normally be uploaded to your remote repo. Did you add the environment variables for production to the Project Settings?
Hi @amyegan
My local .env file is not committed nor is uploaded during deployment to vercel. Instead, it is my understanding that by “connecting a project” the database’s necessary environment variables are made accessible to the project automatically:
Then the @vercel/postgres SDK would take care of getting the corresponding environment variable it needs. This is what I understand from the documentation.
I misread your original post. Yes, the environment variables are automatically managed when you connect a project with Vercel Postgres. That wouldn’t be the problem.
The UND_ERR_CONNECT_TIMEOUT means the connection is timing out. It sometimes happens with missing credentials, which is why I originally suggested that, but it could also be caused by limited serverless function max duration.
If the fetch is requesting a large amount of data, it could take too long and time out. You can try to extended using the maxDuration config or change the request so it returns a smaller chunk of data.
Please give that a try and let me know if it works for you
I am not getting any data back from the database at all, it is a purely log-this-and-basta write to database.
I’m on the Hobby plan, from your link to documentation it looks like that plan’s default serverless function max duration is 10s, which are not reached before that error happens. Upgrading the settings to the “max max duration” for that plan which is 60s doesn’t do anything.
If we’re considering a credentials problem, I’m wondering why in about 10% of the cases the action does result in a write to database?
As a side note (I don’t think it relates to the problem but I might be wrong), I noticed that the POSTGRES_URL environment variable in the Neon storage dashboard specifies the port number while the same environment variable in the project settings doesn’t have it. It doesn’t seem to be a bug or at least it doesn’t seem to matter since I can use the url with or without that port number locally.
Thanks for trying the max duration configuration. We’ve ruled out a credential problem since the Postgres connection is managing that for you and some writes are successful. It sounds like a timing issue or unhandled error in this case.
I recommend using try/catch statements to handle errors and collect more info about what’s going wrong. Runtime logs can also be helpful with this.
So here is a new version of the code that writes to DB (adapted from @vercel/postgres github’s docs):
import { sql, createPool, createClient } from '@vercel/postgres';
export async function addLocation(sessionId: string, lat: number, long: number, isGpsLocation: boolean, message: string | undefined, tagNumber: number | undefined): Promise<void> {
// Instead of this
// sql`INSERT INTO entries (session_id, is_gps, latitude, longitude, message, tag_number) VALUES (${sessionId}, ${isGpsLocation}, ${lat}, ${long}, ${message}, ${tagNumber})`;
console.log('start addLocation');
const client = await sql.connect();
console.log('connected the client')
const { rows } = await client.sql`INSERT INTO entries (session_id, is_gps, latitude, longitude, message, tag_number) VALUES (${sessionId}, ${isGpsLocation}, ${lat}, ${long}, ${message}, ${tagNumber})`;
console.log('contacted the db and got a response')
console.table(rows);
client.release();
console.log('released client');
}
Going several times in a row on the website, that function is called and:
First a few times all the steps are successful, the database is indeed hit and all logs are made;
Then suddenly the function seems to never resolve after the client connection, sometimes with an error (server crash), sometimes without (website displays, no database hit).
Not using sql but the client directly yields a different error (when there is one indeed) that I paste here
Uncaught Exception: Error: Connection terminated unexpectedly
at cn. (file:///var/task/node_modules/@neondatabase/serverless/index.mjs:1250:44)
at Object.onceWrapper (file:///var/task/node_modules/@neondatabase/serverless/index.mjs:410:15)
at cn.emit (file:///var/task/node_modules/@neondatabase/serverless/index.mjs:397:12)
at E. (file:///var/task/node_modules/@neondatabase/serverless/index.mjs:1202:66)
at E.emit (file:///var/task/node_modules/@neondatabase/serverless/index.mjs:397:12)
at WebSocket. (file:///var/task/node_modules/@neondatabase/serverless/index.mjs:989:51)
at callListener (/var/task/node_modules/ws/lib/event-target.js:290:14)
at WebSocket.onClose (/var/task/node_modules/ws/lib/event-target.js:220:9)
at WebSocket.emit (node:events:519:28)
at WebSocket.emitClose (/var/task/node_modules/ws/lib/websocket.js:272:10)
Node.js process exited with exit status: 129. The logs above can help with debugging the issue.
I’m thinking could it be a sort of throttle thing from Neon? But in that case that would be a pretty strict one…
It looks like you’ve tried a few different approaches in the file and have some stray imports. I’m wondering if you get a different result using another method. There are a few different options in the SDK Reference. What happens if you do something like this:
import { sql } from '@vercel/postgres';
export async function addLocation(sessionId: string, lat: number, long: number, isGpsLocation: boolean, message: string | undefined, tagNumber: number | undefined): Promise<void> {
try {
console.log('attempting to connect to database...')
await sql`INSERT INTO entries (session_id, is_gps, latitude, longitude, message, tag_number) VALUES (${sessionId}, ${isGpsLocation}, ${lat}, ${long}, ${message}, ${tagNumber})`;
console.log('done')
} catch (error) {
console.error(error);
}
}
or this:
import { db } from '@vercel/postgres';
export async function addLocation(sessionId: string, lat: number, long: number, isGpsLocation: boolean, message: string | undefined, tagNumber: number | undefined): Promise<void> {
try {
console.log('attempting to connect to database...')
const client = await db.connect();
await client.sql`INSERT INTO entries (session_id, is_gps, latitude, longitude, message, tag_number) VALUES (${sessionId}, ${isGpsLocation}, ${lat}, ${long}, ${message}, ${tagNumber})`;
console.log('done')
} catch (error) {
console.error(error);
}
}