drizzle-team / drizzle-team/drizzle-orm
[BUG]: Drizzle Kit generates incorrect PostgreSQL index operator classes and migration does not create expected tables
- 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.44.7
### What version of `drizzle-kit` are you using?
0.31.10
### Other packages
_No response_
### Describe the Bug
## Summary
I encountered an issue while trying to initialize a new, empty Neon PostgreSQL database from an existing Drizzle schema.
`drizzle-kit generate` successfully generated a migration containing the expected `CREATE TABLE` statements, but one of the generated PostgreSQL indexes contains incorrect operator classes for the column types.
In addition, running `drizzle-kit migrate` against the new database created the internal `drizzle.__drizzle_migrations` table, but the application tables were not present.
I eventually had to execute the generated SQL manually, after correcting the invalid index definition.
## Environment
* PostgreSQL provider: Neon
* Node.js: `22.19.0`
* OS: Windows 11
* TypeScript: `5.9.3`
## Drizzle configuration
```ts
import "dotenv/config";
import { defineConfig } from "drizzle-kit";
export default defineConfig({
dialect: "postgresql",
schema: "./src/schema/**/*.ts",
out: "./migrations",
dbCredentials: {
url: process.env.DATABASE_URL!,
},
});
```
## Schema
The relevant table contains:
```text
user_id -> uuid
expires_at -> timestamp with time zone
```
The generated migration contains the following index:
```sql
CREATE INDEX "idx_auth_sessions_active"
ON "auth_sessions"
USING btree (
"user_id" timestamptz_ops,
"expires_at" uuid_ops
)
WHERE (revoked_at IS NULL);
```
The operator classes appear to be reversed.
The expected definition would be:
```sql
CREATE INDEX "idx_auth_sessions_active"
ON "auth_sessions"
USING btree (
"user_id" uuid_ops,
"expires_at" timestamptz_ops
)
WHERE (revoked_at IS NULL);
```
## Generated migration
The migration correctly contained the expected tables, including:
```sql
CREATE TABLE "auth_sessions" (...);
CREATE TABLE "plans" (...);
CREATE TABLE "products" (...);
CREATE TABLE "subscriptions" (...);
CREATE TABLE "users" (...);
```
It also contained the expected foreign keys and indexes.
However, the generated `idx_auth_sessions_active` index contained the incorrect operator classes described above.
## Migration behavior
The target Neon database was a newly created/empty database.
I ran:
```bash
npx drizzle-kit generate
```
which generated the migration successfully.
Then:
```bash
npx drizzle-kit migrate
```
After migration, the database contained:
```text
drizzle.__drizzle_migrations
```
but the expected application tables were not present.
The migration SQL itself contained the `CREATE TABLE` statements, so the schema was correctly detected by `generate`.
I then executed the generated SQL manually in the Neon SQL editor, after correcting the invalid index definition, and the tables could be created successfully.
## Expected behavior
When generating a migration from a valid Drizzle PostgreSQL schema:
1. PostgreSQL index operator classes should match the underlying column types.
2. `drizzle-kit migrate` should apply the generated migration to a new empty database.
3. The resulting database should contain all tables, constraints, foreign keys and indexes defined by the migration.
4. If a migration fails, the PostgreSQL error should be surfaced clearly so the user can identify which statement caused the failure.
## Actual behavior
* `drizzle-kit generate` generated an index with incompatible/reversed operator classes.
* `drizzle-kit migrate` did not result in the expected application tables being present.
* The internal `drizzle.__drizzle_migrations` table was created.
* Manually executing the corrected SQL created the expected schema.
## Relevant generated SQL
```sql
CREATE INDEX "idx_auth_sessions_active"
ON "auth_sessions"
USING btree (
"user_id" timestamptz_ops,
"expires_at" uuid_ops
)
WHERE (revoked_at IS NULL);
```
## Question
Could this be related to how Drizzle Kit generates PostgreSQL operator classes for composite indexes, particularly when the indexed columns have different PostgreSQL types?
I would also appreciate clarification on whether `drizzle-kit migrate` is expected to create the application tables when initializing a completely new database from a freshly generated migration, and how migration errors are surfaced in this scenario.
Thanks!
Contributor guide
Research direction
Reproduce the issue with drizzle-kit generate and migrate against an empty Neon PostgreSQL database using the reported schema and versions. Inspect the generated migration SQL, especially the composite idx_auth_sessions_active index, and observe whether application tables appear after migration. Done means operator classes match their column types, migration creates all listed tables and indexes, and any failure is clearly surfaced.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- nodejs, postgresql, typescript
- Domain
- databases, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 58/100