Troubleshooting
This guide helps you diagnose and resolve common issues with StrataDB.
Common Installation Issues
Bun Runtime Required
Problem: Error during installation or runtime that mentions bun:sqlite
Solution: StrataDB only works with Bun. Make sure you're using Bun and not Node.js:
# Check if you're using Bun
bun --version
# Install using Bun
bun add stratadb
# Run using Bun
bun run your-script.tsModule Resolution Issues
Problem: Cannot resolve imports like bun:sqlite or stratadb
Solution: Ensure you're running with Bun and using the correct import syntax:
// ✅ Correct import
import { Strata, createSchema } from 'stratadb'
import type { Document } from 'stratadb'Database Connection Issues
File Permission Errors
Problem: Error like "SQLITE_CANTOPEN: unable to open database file"
Solutions:
- Check that the directory exists and is writable:
mkdir -p ./data
chmod 755 ./data- Use absolute paths if relative paths fail:
const db = new Strata({
database: '/absolute/path/to/your/app.db'
})- For temporary databases, use
:memory::
const db = new Strata({ database: ':memory:' })Database Locked Errors
Problem: Error like "SQLITE_BUSY: database is locked"
Solution: This typically occurs with concurrent writes. StrataDB handles most cases automatically, but if you encounter this:
// Use transactions for multiple operations
await db.execute(async (tx) => {
const users = tx.collection('users', userSchema)
// Perform multiple operations in one transaction
await users.insertOne(data1)
await users.insertOne(data2)
})Schema and Query Issues
Invalid Query Operator Errors
Problem: Error like "Query error with operator '$invalidOp': Operator not recognized"
Solution: Check the supported operators. Common mistakes:
// ❌ Invalid - no $contains operator
await users.find({ tags: { $contains: 'admin' } })
// ✅ Correct - use $in for array inclusion
await users.find({ tags: { $in: ['admin'] } })
// ✅ For string contains, use $like with wildcards
await users.find({ name: { $like: '%admin%' } })Type Safety Issues
Problem: TypeScript errors with query filters
Solution: Ensure your schema field types match your query types:
// ❌ Type mismatch - querying number field with string
type User = Document<{ age: number }>
await users.find({ age: 'thirty' }) // TypeScript error
// ✅ Correct - matching types
await users.find({ age: 30 })
await users.find({ age: { $gte: 18 } })Schema Path Validation
Problem: Field not found in query when using nested properties
Solution: Make sure your schema defines the indexed field with correct path:
type User = Document<{
profile: {
bio: string
}
}>
// ❌ This won't work for indexed queries on nested fields
const userSchema = createSchema<User>()
.field('profile', { type: 'TEXT', indexed: true }) // Indexes the whole object
// ✅ Correct - specify the exact path for indexing
const userSchema = createSchema<User>()
.field('profileBio', {
path: '$.profile.bio', // Path to nested property
type: 'TEXT',
indexed: true
})
.build()
// Now this works:
await users.find({ 'profile.bio': 'software engineer' }) // Won't work with custom path
// Instead query what you indexed:
await users.find({ profileBio: 'software engineer' })Performance Issues
Slow Query Performance
Problem: Queries are taking longer than expected
Solutions:
- Check indexing: Ensure frequently queried fields are indexed:
// ❌ Unindexed query - slow
const users = await users.find({ email: 'user@example.com' })
// ✅ Indexed query - fast
const userSchema = createSchema<User>()
.field('email', { type: 'TEXT', indexed: true })
.build()- Use query caching for repeated patterns:
// Enable caching for frequently repeated queries
const db = new Strata({
database: 'app.db',
enableCache: true
})- Optimize complex queries:
// ❌ Multiple OR conditions can be slow
await users.find({
$or: [
{ status: 'active' },
{ status: 'pending' },
{ status: 'trial' }
]
})
// ✅ Single $in query is more efficient
await users.find({ status: { $in: ['active', 'pending', 'trial'] } })Memory Usage Issues
Problem: High memory usage with query caching enabled
Solution: Monitor and limit cache size:
// Disable caching for collections with varied queries
const oneOffQueries = db.collection('temp', schema, { enableCache: false })
// Or limit the cache size by disabling global cache and enabling only where needed
const db = new Strata({
database: 'app.db',
enableCache: false // Disable globally
})
const frequentlyUsed = db.collection('users', userSchema, { enableCache: true })Validation and Data Issues
Unique Constraint Violations
Problem: UniqueConstraintError when inserting documents
Solutions:
- Check for duplicates before inserting:
const existing = await users.findOne({ email: newEmail })
if (!existing) {
await users.insertOne(newUser)
}- Use upsert operations:
await users.updateOne(
{ email: 'user@example.com' }, // Search criteria
{ name: 'Updated Name' }, // Update data
{ upsert: true } // Insert if not found
)- Handle the error gracefully:
try {
await users.insertOne(newUser)
} catch (error) {
if (error instanceof UniqueConstraintError) {
if (error.field === 'email') {
// Handle duplicate email
throw new Error('Email already registered')
}
}
throw error // Re-throw other errors
}Validation Errors
Problem: ValidationError when inserting documents
Solutions:
- Validate before insertion:
try {
const validatedUser = userSchema.validate(userData)
if (validatedUser) {
await users.insertOne(userData)
}
} catch (error) {
if (error instanceof ValidationError) {
console.log(`Validation failed: ${error.message}`)
}
}- Debug validation issues:
// Use validateSync for synchronous validation
try {
const validated = userSchema.validateSync(userData)
await users.insertOne(validated)
} catch (error) {
console.log('Validation error:', error)
console.log('Problematic field:', error.field)
console.log('Value that failed:', error.value)
}Transaction Issues
Transaction Rollback Issues
Problem: Transaction doesn't rollback when expected
Solution: Make sure to properly handle errors in transactions:
// ✅ Using execute helper (recommended)
const result = await db.execute(async (tx) => {
const usersTx = tx.collection('users', userSchema)
// If any operation throws, transaction automatically rolls back
await usersTx.insertOne(userData)
return { success: true }
})
// ✅ Manual transaction with proper error handling
const tx = db.transaction()
try {
const users = tx.collection('users', userSchema)
await users.insertOne(userData)
await users.updateOne(someId, updateData)
tx.commit()
} catch (error) {
// tx.rollback() is called automatically by Symbol.dispose if not committed
throw error
}Nested Transaction Issues
Problem: Issues with nested or concurrent transactions
Solution: StrataDB doesn't support nested transactions. Instead, pass transaction context:
// ❌ Don't create nested transactions
async function outerFunction() {
return await db.execute(async (tx1) => {
await innerFunction() // This might try to create another transaction
})
}
async function innerFunction() {
return await db.execute(async (tx2) => { // ❌ Creates nested transaction
// operations
})
}
// ✅ Pass transaction to inner functions
async function outerFunction() {
return await db.execute(async (tx) => {
await innerFunction(tx) // Pass the existing transaction
})
}
async function innerFunction(tx: Transaction) {
const users = tx.collection('users', userSchema)
// Use the passed transaction
return await users.find({})
}Advanced Troubleshooting
Debugging Slow Queries
Enable query logging to see the actual SQL being executed:
// Add logging middleware (not built-in, but you can create one)
const originalFind = users.find
users.find = async function(...args) {
console.time('find operation')
const result = await originalFind.apply(this, args)
console.timeEnd('find operation')
return result
}Memory Leaks
If experiencing memory issues:
- Close databases properly:
// Use Symbol.dispose for automatic cleanup
using db = new Strata({ database: 'app.db' })
// db.close() called automatically when scope exits
// Or manually close
const db = new Strata({ database: 'app.db' })
// ... use db ...
db.close()- Monitor collection instances - avoid creating many collection instances:
// ❌ Don't create collections repeatedly
function processUser(userId: string) {
const users = db.collection('users', userSchema) // New instance each time
return users.findById(userId)
}
// ✅ Create collection once and reuse
const users = db.collection('users', userSchema)
function processUser(userId: string) {
return users.findById(userId) // Reuse same instance
}Testing Issues
Problem: Testing code that uses StrataDB
Solution: Use in-memory databases for tests:
import { describe, test, expect, beforeEach, afterEach } from 'bun:test'
describe('User Service', () => {
let db: Strata
let users: Collection<User>
beforeEach(() => {
// Use in-memory database for tests
db = new Strata({ database: ':memory:' })
users = db.collection('users', userSchema)
})
afterEach(() => {
db.close()
})
test('should create user', async () => {
const result = await users.insertOne(userData)
expect(result.document.id).toBeDefined()
})
})Getting Help
If you encounter issues not covered here:
- Check the API documentation for method signatures and options
- Review the examples in the guide documentation
- Search for similar issues in the repository (if open source)
- Create a minimal reproduction to isolate the problem
For debugging, consider creating a minimal example that reproduces your issue:
// Example of a minimal reproduction
import { Strata, createSchema, type Document } from 'stratadb'
type TestDoc = Document<{ name: string }>
const schema = createSchema<TestDoc>()
.field('name', { type: 'TEXT', indexed: true })
.build()
const db = new Strata({ database: ':memory:' })
const collection = db.collection('test', schema)
try {
await collection.insertOne({ name: 'test' })
console.log('Success!')
} catch (error) {
console.error('Error:', error)
} finally {
db.close()
}