drizzle-team / drizzle-team/drizzle-orm
[BUG]: Unable to connect to Supabase in Development. SSL Errors: (Error: SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature is missing AND/OR SELF_SIGNED_CERT_IN_CHAIN
- Dominant language
- TypeScript
- Stars
- 35.8k
- Forks
- 1.6k
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 4
Description
### Report hasn't been filed before.
- [x] I have verified that the bug I'm about to report hasn't been filed before.
### What version of `drizzle-orm` are you using?
0.43.1
### What version of `drizzle-kit` are you using?
0.31.1
### Other packages
_No response_
### Describe the Bug
### Undesired behavior:
When attempting a connecting to a Supabase database for example for a simple migration (drizzle-kit push) the connection fails with one of two errors depending on various configurations in the drizzle.config.ts file. Either the error is:
`Error: SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature is missing`
or:
`Error: self-signed certificate in certificate chain SELF_SIGNED_CERT_IN_CHAIN`
### Steps to reproduce the behavior
Use any of the recommended configurations in either the Supabase docs or the Drizzle docs showing how to connect to Supabase with Drizzle-ORM in the drizzle.config.ts file.
```
import { defineConfig } from 'drizzle-kit';
import env from '@/env'; // I use an env.ts file to get type safety with environment variables using zod
export default defineConfig({
schema: './src/db/schema.ts',
out: './src/db/migrations',
dialect: 'postgresql',
dbCredentials: {
url: env.DATABASE_URL,
},
schemaFilter: ['public'],
verbose: true,
strict: true,
});
```
I use an env.ts file to get type safety with zod when I use environment variables. I also use dotenvx to inject the environment variables before my other scripts, but I confirmed with console.logs that my environment variables were being output correctly and others have had the same issues using dotenv to manage process.env.
The error I get is `Error: SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature is missing`
In this example the database URL includes a URI encoded version of my Supabase password following this format:
`postgres://postgres.apbkobhfnmcqqzqeeqss:[MY-PASSWORD]@aws-0-[REGION].pooler.supabase.com:6543/postgres`
I have tried using both ports 6543 and 5432 and both have the same results in all configurations.
I tried adding `?sslmode=require` to the end of my DATABASE_URL but then I get the `Error: self-signed certificate in certificate chain SELF_SIGNED_CERT_IN_CHAIN` error. I have also tried adding: `?sslmode=no-verify` instead which also returns an error.
I also tried this configuration:
```
import { defineConfig } from 'drizzle-kit';
import env from '@/env';
import fs from 'fs';
const {
DATABASE_HOST: host, // The host part of the Supabase connection string
DATABASE_USER: user, // The user string "postgres.[user_string]"
DATABASE_NAME: database, // "postgres"
DATABASE_PASSWORD: password, // Some passwords contain special characters, but I got the same errors regardless
DATABASE_PORT: port, // I tried both 5432 and 6543 to no avail
} = env;
const connectionString = `postgresql://${user}:${encodeURIComponent(password)}@${host}:${port}/${database}`;
export default defineConfig({
schema: './src/db/schema.ts',
out: './src/db/migrations',
dialect: 'postgresql',
dbCredentials: {
url: connectionString,
},
schemaFilter: ['public'],
verbose: true,
strict: true,
});
```
and the following:
```
import { defineConfig } from 'drizzle-kit';
import env from '@/env';
import fs from 'fs';
export default defineConfig({
schema: './src/db/schema.ts',
out: './src/db/migrations',
dialect: 'postgresql',
dbCredentials: {
host: env.DATABASE_HOST,
user: env.DATABASE_USER,
password: env.DATABASE_PASSWORD,
database: env.DATABASE_NAME,
ssl: { rejectUnauthorized: false },
},
schemaFilter: ['public'],
verbose: true,
strict: true,
});
```
I tried changing the ssl property to `{ rejectUnauthorized: true }` or also "require" and got the same errors. I tried different combinations of all of the above by adding different `?sslmode=[option]` variations to the end of my url as well. Nothing worked.
When I checked my Supabase logs the connection was being "received" and "authorized" and "authenticated" with no errors. When I tried to connect with psql using the same connection string I had no problems.
I also tried adding this to the ssl property in drizzle.config.ts:
```
ssl: {
ca: fs.readFileSync(env.DATABASE_CA).toString()
}
```
and downloaded my certificate from Supabase and put it in my project directory (not checked into version control, of course) and added an environment variable with the filepath. Still got the same errors.
Finally, since I am on a Windows system, I switched over to WSL using Ubuntu and tried all the same combinations with no luck.
### Desired Result
With the project running on WSL, I tried changing my Supabase password and still got the same errors until I finally downloaded the certificate and setup my drizzle.config.ts like this:
```
import { defineConfig } from 'drizzle-kit';
import env from '@/env';
import fs from 'fs';
export default defineConfig({
schema: './src/db/schema.ts',
out: './src/db/migrations',
dialect: 'postgresql',
dbCredentials: {
url: env.DATABASE_URL,
ssl: {
ca: fs.readFileSync(env.DATABASE_CA).toString(),
rejectUnauthorized: true,
}
},
schemaFilter: ['public'],
verbose: true,
strict: true,
});
```
The connection was made, but then forcibly closed. I attempted again and the migration worked: my table was created in Supabase via drizzle-kit push. This is the desired outcome.
### What needs to be done
There is virtually no documentation reflecting this issue or how to properly setup the drizzle.config.ts to manage this issue. Despite from my working example, this still doesn't seem to be desired behavior. There is something wrong with how Drizzle is handling connections with Supabase and SSL. I can't yet confirm if this issue exists in production. However, when I used psql to connect to supabase using the same DATABASE_URL (with "?sslmode=require") it connected perfectly without error. This seems to be a drizzle-specific issue, and a significant one. Not being able to properly configure connecting to my database in a desirable or efficient way (and a way that is even documented) makes this tool unstable and unreliable.
I would suggest adding specific documentation regarding this potential issue with Supabase and the best practice for resolving it (I'm not saying my case is best practice - but it seems to be the only way I can get it to work in development). I also suggest finding a better way to handle the SSL certificate handshake. Like I said, psql had no issue, but I'm not sure what all the differences are with Drizzle that would create this issue.
Contributor guide
Assessment
This issue has not been assessed yet.