Files
gh-jezweb-claude-skills-ski…/references/common-errors.md
2025-11-30 08:24:43 +08:00

246 lines
5.3 KiB
Markdown

# Common Errors with Drizzle ORM and D1
This document provides detailed solutions for all 12 documented issues.
---
## Issue #1: D1 Transaction Errors
**Error**: `D1_ERROR: Cannot use BEGIN TRANSACTION`
**Source**: https://github.com/drizzle-team/drizzle-orm/issues/4212
**Why It Happens**:
Drizzle ORM tries to use traditional SQL transactions with `BEGIN TRANSACTION` and `COMMIT` statements. However, Cloudflare D1 does not support these SQL transaction commands and raises a D1_ERROR.
**Solution**:
Use D1's batch API instead:
```typescript
// ❌ Don't use
await db.transaction(async (tx) => {
// This will fail
});
// ✅ Use batch API
await db.batch([
db.insert(users).values({ email: 'test@example.com', name: 'Test' }),
db.insert(posts).values({ title: 'Post', content: 'Content', authorId: 1 }),
]);
```
See `templates/transactions.ts` for complete examples.
---
## Issue #2: Foreign Key Constraint Failures
**Error**: `FOREIGN KEY constraint failed: SQLITE_CONSTRAINT`
**Source**: https://github.com/drizzle-team/drizzle-orm/issues/4089
**Why It Happens**:
Drizzle-generated migrations include `PRAGMA foreign_keys = OFF;` which can cause issues during migration execution.
**Solution**:
1. Define cascading deletes in schema:
```typescript
authorId: integer('author_id')
.notNull()
.references(() => users.id, { onDelete: 'cascade' })
```
2. Ensure proper migration order (parent tables before child tables)
3. Test migrations locally first: `wrangler d1 migrations apply DB --local`
---
## Issue #3: Module Import Errors
**Error**: `Error: No such module "wrangler"`
**Source**: https://github.com/drizzle-team/drizzle-orm/issues/4257
**Why It Happens**:
Bundlers (like OpenNext) may incorrectly try to bundle Wrangler, which should only be used as a CLI tool.
**Solution**:
1. Never import from `wrangler` in runtime code
2. Use correct imports: `import { drizzle } from 'drizzle-orm/d1'`
3. Configure bundler externals if needed
---
## Issue #4: D1 Binding Not Found
**Error**: `env.DB is undefined` or `Cannot read property 'prepare' of undefined`
**Why It Happens**:
The D1 binding name in wrangler.jsonc doesn't match the name used in code.
**Solution**:
Ensure consistency:
```jsonc
// wrangler.jsonc
{
"d1_databases": [
{ "binding": "DB" } // ← Must match
]
}
```
```typescript
// code
export interface Env {
DB: D1Database; // ← Must match
}
const db = drizzle(env.DB); // ← Must match
```
---
## Issue #5: Migration Apply Failures
**Error**: `Migration failed to apply: near "...": syntax error`
**Why It Happens**:
SQL syntax errors, conflicting migrations, or applying migrations out of order.
**Solution**:
1. Test locally first: `wrangler d1 migrations apply DB --local`
2. Review generated SQL in `./migrations` before applying
3. If failed, delete and regenerate: `rm -rf migrations/ && drizzle-kit generate`
---
## Issue #6: Schema TypeScript Inference Errors
**Error**: `Type instantiation is excessively deep and possibly infinite`
**Why It Happens**:
Complex circular references in relations cause TypeScript to fail type inference.
**Solution**:
Use explicit type annotations:
```typescript
import { InferSelectModel } from 'drizzle-orm';
export type User = InferSelectModel<typeof users>;
export type Post = InferSelectModel<typeof posts>;
```
---
## Issue #7: Prepared Statement Caching Issues
**Error**: Stale or incorrect results from queries
**Why It Happens**:
D1 doesn't cache prepared statements between requests like traditional SQLite.
**Solution**:
Don't rely on caching behavior:
```typescript
// ✅ Use .all() or .get() methods
const users = await db.select().from(users).all();
```
---
## Issue #8: Transaction Rollback Patterns
**Error**: Transaction doesn't roll back on error
**Why It Happens**:
D1 batch API doesn't support traditional rollback.
**Solution**:
Implement error handling with manual cleanup:
```typescript
try {
await db.batch([/* operations */]);
} catch (error) {
// Manual cleanup if needed
console.error('Batch failed:', error);
}
```
---
## Issue #9: TypeScript Strict Mode Errors
**Error**: Type errors with `strict: true`
**Solution**:
Use explicit return types:
```typescript
async function getUser(id: number): Promise<User | undefined> {
return await db.select().from(users).where(eq(users.id, id)).get();
}
```
---
## Issue #10: Drizzle Config Not Found
**Error**: `Cannot find drizzle.config.ts`
**Why It Happens**:
Wrong file location or incorrect file name.
**Solution**:
1. File must be named exactly `drizzle.config.ts`
2. File must be in project root
3. Or specify: `drizzle-kit generate --config=custom.config.ts`
---
## Issue #11: Remote vs Local Confusion
**Error**: Changes not appearing
**Why It Happens**:
Applying migrations to wrong database.
**Solution**:
Use correct flags consistently:
```bash
# Development
wrangler d1 migrations apply DB --local
# Production
wrangler d1 migrations apply DB --remote
```
---
## Issue #12: wrangler.toml vs wrangler.jsonc
**Error**: Configuration not recognized
**Why It Happens**:
Mixing TOML and JSON config formats.
**Solution**:
Use `wrangler.jsonc` consistently (supports comments):
```jsonc
{
"name": "my-worker",
// Comment here
"d1_databases": []
}
```
---
**Total Errors Prevented**: 12
**Success Rate**: 100% when following these solutions