drizzle-team / drizzle-team/drizzle-orm

[BUG]: Transaction leaks a promise that never resolves or rejects

Open
#4,824 4 comments 0 reactions 0 assignees View on GitHub
bug
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.4

### What version of `drizzle-kit` are you using?

0.31.1

### Other packages

drizzle-typebox@0.3.3

### Describe the Bug

I am using a postgres container version 17.4 using bun 1.2.19

I had a test that it always passed in **0.43.1** and now has become flaky; sometimes it passes and sometimes it doesn't.

When it doesn't pass it's because the test times out despite the error is being logged.

# The test
```ts
it('should create a location and throw ConflictError if the location code already exists', async () => {
await expect(createLocation({
name: 'testlocation',
companyId: company.id,
locationCode: 'OVD',
address: 'Some sort of address',
city: 'Madrid'
})).resolves.toBeDefined()

await expect(createLocation({
name: 'testlocation2',
companyId: company.id,
locationCode: 'OVD',
address: 'Another address',
city: 'Barcelona'
})).rejects.toThrow(ConflictError)
})
```

# The test output
```txt
✗ should create a location and throw ConflictError if the location code already exists [5001.29ms]

# Unhandled error between tests
-------------------------------
37 | name: 'testlocation2',
38 | companyId: company.id,
39 | locationCode: 'OVD',
40 | address: 'Another address',
41 | city: 'Barcelona'
42 | })).rejects.toThrow(ConflictError)
^
error: expect(received).toThrow(expected)

Expected constructor: ConflictError
Received constructor: Error

Received message: "terminating connection due to administrator command"
```

```ts
interface CreateLocationOptions {
companyId: string
name: string,
locationCode: string,
address: string
city: string
}
export async function createLocation(newLocation: CreateLocationOptions) {
const l = await db.transaction(async (tx) => {
try {
const [l] = await tx.insert(location).values(newLocation).returning()
await tx.insert(locationCounters).values({
locationId: l.id,
counter: 0
})
return l
} catch(err) {

// Yes I had to adapt this line to include the checks for DrizzleQueryError when upgrading to the latest version
if(err instanceof DrizzleQueryError && err.cause && "constraint" in err.cause && err.cause.constraint === 'unique_location_code') {
log.error('Unable to create location', { error: err, cname: err?.constructor?.name})
throw new ConflictError('El código de la ubicación ya existe')
}

throw err
}
})
log.debug(`Created location with ID ${l.id}`)

return l
}
```

And the logs:

```
debug: Created location with ID 3f2c53a4-d358-4673-bed9-d4c5eaa5037f {"file":"data/locations.ts","service":"issue-tracker-0","timestamp":"2025-08-03T15:20:53.031Z"}
error: Unable to create location {"cname":"DrizzleQueryError","error":{"cause":{"constraint":"unique_location_code","detail":"Key (location_code)=(OVD) already exists.","errno":"23505","schema":"public","table":"location"},"params":["a6918bee-2baa-43b5-9465-d343321e587c","testlocation2","OVD","Another address","Barcelona"],"query":"insert into \"location\" (\"id\", \"company_id\", \"name\", \"location_code\", \"address\", \"city\", \"created_at\", \"updated_at\") values (default, $1, $2, $3, $4, $5, default, default) returning \"id\", \"company_id\", \"name\", \"location_code\", \"address\", \"city\", \"created_at\", \"updated_at\""},"file":"data/locations.ts","service":"issue-tracker-0","timestamp":"2025-08-03T15:20:53.033Z"}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.