postgres icon indicating copy to clipboard operation
postgres copied to clipboard

Deno - error: Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'replace')

Open bidipeppercrap opened this issue 1 year ago • 10 comments

image image

Spec

Runtime: Deno Database Provider: Neon

Reproduce:

I run into this error when I try to migrate.

Code

deno.json

{
    "imports": {
        "db/": "./src/db/",
        "kysely": "npm:kysely@^0.27.2",
        "kysely-postgres-js": "npm:kysely-postgres-js@^2.0.0",
        "postgres": "https://deno.land/x/[email protected]/mod.js"
    },
    "tasks": {
        "migrate": "deno run -A ./src/db/migrator.ts"
    }
}

migrator:

import * as path from "node:path";
import { fileURLToPath } from "node:url";
import { promises as fs } from "node:fs";
import { Migrator, FileMigrationProvider } from "kysely";
import { db } from "db/database.ts";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

async function migrateToLatest() {
    const migrator = new Migrator({
        db,
        provider: new FileMigrationProvider({
            fs,
            path,
            migrationFolder: path.join(__dirname, "./migrations")
        })
    });

    const { error, results } = await migrator.migrateToLatest();

    results?.forEach((it) => {
        if (it.status === "Success") {
            console.log(`migration "${it.migrationName}" was executed successfully`);
        } else if (it.status === "Error") {
            console.error(`failed to execute migration "${it.migrationName}"`);
        }
    });

    if (error) {
        console.error("failed to migrate");
        console.error(error);
        Deno.exit(1);
    }

    await db.destroy();
}

migrateToLatest();

db instance:

import { Database } from "db/types/index.ts";
import postgres from "postgres";
import { Kysely } from "kysely";
import { PostgresJSDialect } from "kysely-postgres-js";
import { load } from "https://deno.land/[email protected]/dotenv/mod.ts";

const env = await load();

const dialect = new PostgresJSDialect({
    postgres: postgres({
        database: env["PGDATABASE"]!,
        host: env["PGHOST"]!,
        user: env["PGUSER"]!,
        password: env["PGPASSWORD"]!,
        port: 5434,
        max: 10,
    })
});

export const db = new Kysely<Database>({
    dialect
});

bidipeppercrap avatar Jan 15 '24 13:01 bidipeppercrap

Have you found solution?

skelawsky avatar Feb 11 '24 13:02 skelawsky

Same problem with nextjs node or bun doesn't matter

lpite avatar Mar 01 '24 07:03 lpite

Same problem with nextjs node or bun doesn't matter

I found it worked with Node

Only in Deno it is not working.

bidipeppercrap avatar Mar 01 '24 08:03 bidipeppercrap

Same problem with nextjs node or bun doesn't matter

I found it worked with Next.js Typescript

Only in Deno it is not working.

It's working in production I guess but on dev it can work for a while but then on hot reload this error happens

lpite avatar Mar 01 '24 19:03 lpite

Same problem with nextjs node or bun doesn't matter

I found it worked with Next.js Typescript Only in Deno it is not working.

It's working in production I guess but on dev it can work for a while but then on hot reload this error happens

This is a matter of migrating It worked with Node or npm run migrate... But doesn't work with deno task migrate...

bidipeppercrap avatar Mar 02 '24 01:03 bidipeppercrap

I'm having this issue when reserving but not with regular connections. @porsager could really use your help here.

const admin = pg(databaseUrl, { database: "postgres" })

return {
  admin: await admin.reserve()
}

Crashes:

node_modules/.pnpm/[email protected]/node_modules/postgres/src/connection.js:389
      stack: { value: err.stack + query.origin.replace(/.*\n/, '\n'), enumerable: options.debug },
                                               ^

TypeError: Cannot read properties of undefined (reading 'replace')

Heads up that doing

await admin.unsafe("SELECT 1")

Solved the issue for me.

divmgl avatar Mar 05 '24 03:03 divmgl

The problem occurs when I open my Mac after a couple of hours. This is a bug in error handling routine and obscures the real error. 100% should be fixed in this package.

file:///Users/epi/projects/hs4/node_modules/postgres/src/connection.js:389
      stack: { value: err.stack + query.origin.replace(/.*\n/, '\n'), enumerable: options.debug },
                                               ^

TypeError: Cannot read properties of undefined (reading 'replace')
    at queryError (file:///Users/epi/projects/hs4/node_modules/postgres/src/connection.js:389:48)
    at errored (file:///Users/epi/projects/hs4/node_modules/postgres/src/connection.js:383:14)
    at Socket.data (file:///Users/epi/projects/hs4/node_modules/postgres/src/connection.js:318:9)
    at Socket.emit (node:events:514:28)
    at Socket.emit (node:domain:488:12)
    at addChunk (node:internal/streams/readable:376:12)
    at readableAddChunk (node:internal/streams/readable:349:9)
    at Readable.push (node:internal/streams/readable:286:10)
    at TCP.onStreamRead (node:internal/stream_base_commons:190:23)

Node.js v20.9.0
npm ERR! Lifecycle script `dev` failed with error: 
npm ERR! Error: command failed 
npm ERR!   in workspace: [email protected] 
npm ERR!   at location: /Users/epi/projects/hs4/packages/backend 

episage avatar Mar 06 '24 10:03 episage

Found the offending line:

image
Query:
{
  reserve: [Function (anonymous)],
  state: { pid: 17618, secret: 131674580 },
  active: true
}
Error:
TypeError: Cannot read properties of undefined (reading '0')
    at build (file:///Users/epi/projects/hs4/node_modules/postgres/src/connection.js:223:42)
    at execute (file:///Users/epi/projects/hs4/node_modules/postgres/src/connection.js:167:7)
    at ReadyForQuery (file:///Users/epi/projects/hs4/node_modules/postgres/src/connection.js:568:27)
    at handle (file:///Users/epi/projects/hs4/node_modules/postgres/src/connection.js:503:6)
    at Socket.data (file:///Users/epi/projects/hs4/node_modules/postgres/src/connection.js:315:9)
    at Socket.emit (node:events:514:28)
    at Socket.emit (node:domain:488:12)
    at addChunk (node:internal/streams/readable:376:12)
    at readableAddChunk (node:internal/streams/readable:349:9)
    at Readable.push (node:internal/streams/readable:286:10)

episage avatar Mar 12 '24 02:03 episage

We saw this issue as well in our production environments after starting to use kysely-postgres-js.

We managed to track it down to the fact that initial is sometimes set to true and sometime to a query, it also seems to be true more frequently when reserving connections using reserve(). This is what kysely-postgres-js does under the hood, and also when @divmgl saw it. The current "workaround" is to use the suggestion from @divmgl and add a await sql.unsafe('SELECT 1') before the connection is reserved. By doing this we get the actual error message.

The minimal code to reproduce this issue is to run the code below while your postgres instance is shutting down;

    const sql = postgres({
        ...
    });
    const reserved = await sql.reserve();
    await reserved.unsafe('SELECT 1');

initial could potentially be set to true here; https://github.com/porsager/postgres/blob/f58cd4f3affd3e8ce8f53e42799672d86cd2c70b/src/connection.js#L108-L114

But expected to be a query here; https://github.com/porsager/postgres/blob/f58cd4f3affd3e8ce8f53e42799672d86cd2c70b/src/connection.js#L384-L397

When running the reproduction code above, we could see that query=true in queryError(query, err) { ... }

coder-se avatar Jun 07 '24 13:06 coder-se

To replicate the problem:

  1. Turn off your SQL server.
  2. Use .reserve().

The error is shadowed with another one throwing in postgres/src/connection.js because query is true instead of actual query.

 + query.origin.replace(/.*\n/, '\n')
image

episage avatar Jun 15 '24 08:06 episage