Skip to content
Get started
Get started

Troubleshooting bunqueue: Common Issues & Fixes

reference · troubleshooting

Troubleshooting, cause and fix.

Symptoms, causes and fixes for the issues people actually hit: SQLite locks, embedded mode misconfiguration, stuck jobs, half-open connections and backup failures.

”bunqueue is Bun-only and requires the Bun runtime”

Section titled “”bunqueue is Bun-only and requires the Bun runtime””

Running under Node.js throws:

bunqueue is Bun-only and requires the Bun runtime (https://bun.sh). Node.js is not supported: install Bun and run your program with bun.

bunqueue only works with Bun (v1.3.9+), not Node.js, run your program with bun, not node.

Terminal window
# Check if Bun is installed
bun --version
# Install Bun if needed
curl -fsSL https://bun.sh/install | bash
Terminal window
# Try with sudo (not recommended)
sudo bun add bunqueue
# Better: fix npm permissions
mkdir ~/.bun
chown -R $(whoami) ~/.bun

Multiple processes trying to write simultaneously.

Solutions:

  1. Use WAL mode (default in bunqueue)
  2. Ensure only one server instance per database file
  3. Use server mode for multi-process access
Terminal window
# Check for multiple processes
lsof ./data/queue.db
# Kill stale processes
pkill -f bunqueue

”SQLITE_CORRUPT: database disk image is malformed”

Section titled “”SQLITE_CORRUPT: database disk image is malformed””

Database corruption, usually from crash during write.

Solutions:

  1. Restore from S3 backup
  2. Delete and recreate database (data loss)
Terminal window
# Restore from backup
bunqueue backup list
bunqueue backup restore <key> --force
# Or recreate (loses data)
rm ./data/queue.db*
bunqueue start

SQLite doesn’t automatically reclaim space.

Terminal window
# Vacuum the database (run when server is stopped)
sqlite3 ./data/queue.db "VACUUM;"
# Enable auto-vacuum (before creating database)
sqlite3 ./data/queue.db "PRAGMA auto_vacuum = INCREMENTAL;"
error: Command timeout
queue: "my-queue",
context: "pull"

This error means your Worker is trying to connect to a TCP server instead of using embedded mode.

Solution: Add embedded: true to both Queue and Worker:

// WRONG - Worker defaults to TCP mode
const queue = new Queue('tasks', { embedded: true });
const worker = new Worker('tasks', processor); // Missing embedded: true!
// CORRECT - Both have embedded: true
const queue = new Queue('tasks', { embedded: true });
const worker = new Worker('tasks', processor, { embedded: true });

The database is only created when a data path is configured.

Solution (embedded mode):

import { Queue, Worker } from 'bunqueue/client';
// Pass dataPath directly
const queue = new Queue('tasks', { embedded: true, dataPath: './data/bunqueue.db' });
const worker = new Worker('tasks', processor, { embedded: true, dataPath: './data/bunqueue.db' });

Solution (server mode): Use a configuration file or set DATA_PATH:

Terminal window
DATA_PATH=./data/bunqueue.db bunqueue start

In embedded mode the shared QueueManager is a singleton that is initialized by the first Queue or Worker constructed in the process. If no data path is known at that moment, it opens in-memory and later configuration has no effect.

Common pitfall: setting process.env.DATA_PATH at the top of main.ts and then importing a module that constructs a Queue/Worker. ESM imports are hoisted, so the module (and its constructors) run before the assignment.

Solution 1 (recommended): pass dataPath directly in the constructor options, no env var needed:

const queue = new Queue('tasks', { embedded: true, dataPath: './data/bunqueue.db' });
const worker = new Worker('tasks', processor, { embedded: true, dataPath: './data/bunqueue.db' });

Solution 2: set the env var before the process starts:

Terminal window
BUNQUEUE_DATA_PATH=./data/bunqueue.db bun run main.ts

Worker crashed while processing.

Solutions:

  1. Enable stall detection
  2. Restart workers
queue.setStallConfig({
enabled: true,
stallInterval: 30000,
maxStalls: 3,
});

Check these:

  1. Is the queue paused?
  2. Is there a worker for this queue?
  3. Is rate limiting blocking jobs?
// Check if paused
const isPaused = await queue.isPausedAsync();
// Check counts
const counts = await queue.getJobCounts();
console.log(counts);

”Job is not active” when calling updateProgress

Section titled “”Job is not active” when calling updateProgress”

Progress can only be updated while the job is active (being processed). The server rejects Progress for any other state with Job is not active (current state: ...). Typical causes:

  • Calling job.updateProgress() after the processor returned (job already completed)
  • The job was failed/stalled/cancelled underneath a long-running processor
  • Updating progress from outside the worker while the job is still waiting

Treat it as a signal that you no longer own the job, not as a transient error.

getJobs() does not show a job I just added

Section titled “getJobs() does not show a job I just added”

Job listings (getJobs, GetJobs over TCP) read from SQLite, while pushes go through a write buffer that flushes about every 10ms. A job added a moment ago can be missing from a listing for up to ~10ms. Use getJob(id) / getState(id) (which read the in-memory index) for read-after-write checks, or add the job with durable: true to bypass the buffer.

Check the error in failed event:

worker.on('failed', (job, error) => {
console.error('Job failed:', error);
console.error('Job data:', job.data);
console.error('Attempts:', job.attemptsMade);
});

Possible causes:

  1. Jobs not being removed after completion
  2. Too many jobs in DLQ
  3. Memory leak in processor
// Enable removeOnComplete
await queue.add('task', data, {
removeOnComplete: true,
});
// Purge old DLQ entries
queue.purgeDlq();
// Check for leaks in processor
worker.on('completed', () => {
console.log('Memory:', process.memoryUsage().heapUsed);
});

Server not running or wrong port.

Terminal window
# Check if server is running
ps aux | grep bunqueue
# Check listening ports
lsof -i :6789
lsof -i :6790
# Start server
bunqueue start

Network issues or server overload.

// Add reconnection logic
let client = createClient();
client.on('error', async () => {
await sleep(1000);
client = createClient();
});

Worker stalls on a half-open connection (throughput drops to 0)

Section titled “Worker stalls on a half-open connection (throughput drops to 0)”

A worker’s TCP socket can go half-open, the peer vanishes with no FIN/RST (host suspended/hibernated, NAT or load-balancer silently dropping an idle connection). Writes still succeed and no close event fires, so the symptom is: every command rejects with Command timeout, consecutiveErrors climbs, jobs pile up in waiting with active=0, and throughput sits at 0.

bunqueue detects this and reconnects automatically via two signals: the health-check ping (maxPingFailures) and consecutive command timeouts (maxCommandTimeouts, default 3). With default timings (pingInterval/commandTimeout = 30s) recovery takes up to ~120s. For faster recovery, tighten the detection cadence:

const worker = new Worker('q', handler, {
connection: {
host, port,
pingInterval: 10_000, // health-check every 10s (0 disables)
commandTimeout: 5_000, // fail a command after 5s
maxCommandTimeouts: 3, // 3 consecutive timeouts → reconnect (0 disables)
},
});

This recovers in ~tens of seconds and works even with the ping disabled. If a fresh connection also can’t be established (e.g. the server is genuinely unreachable, a firewall dropping inbound SYNs, not just an idle drop), no client can reconnect until connectivity returns; auto-reconnect with infinite attempts resumes on its own once it does.

Terminal window
# Check token is set
echo $AUTH_TOKENS
# Test with curl
curl -H "Authorization: Bearer your-token" \
http://localhost:6790/health

Optimize:

  1. Increase worker concurrency
  2. Use batch operations
  3. Check database I/O
// Increase concurrency
const worker = new Worker('queue', processor, {
concurrency: 20,
});
// Use bulk add
await queue.addBulk([...jobs]);
// Workers batch pulls and acks automatically; tune the batch size
const batchWorker = new Worker('queue', processor, { batchSize: 100 });

Check:

  1. Index on queue table
  2. Too many delayed jobs
  3. Database on slow disk
-- Check indexes exist
.indices jobs
-- Check delayed jobs count
SELECT COUNT(*) FROM jobs WHERE state = 'delayed';

Too many connections or jobs.

Terminal window
# Check connection count
bunqueue stats
# Reduce polling frequency
# Add backoff in clients
Terminal window
# Check credentials
echo $S3_ACCESS_KEY_ID
echo $S3_BUCKET
# Test connectivity
aws s3 ls s3://$S3_BUCKET/
# Check logs
bunqueue backup status
Terminal window
# List available backups
bunqueue backup list
# Force restore (overwrites existing)
bunqueue backup restore <key> --force

Segmentation fault when terminating workers

Section titled “Segmentation fault when terminating workers”

If you experience crashes (segfaults) when using SandboxedWorker, especially during worker timeout or error handling, this is a known Bun bug.

Symptoms:

  • Segmentation fault at address 0xE8
  • Worker has been terminated errors
  • Crashes during worker.terminate() calls
  • Unexpected memory growth or thread duplication (#52)

Solution: Switch to the standard Worker for production workloads:

// ❌ SandboxedWorker: experimental, may crash
const worker = new SandboxedWorker('queue', {
processor: './processor.ts',
concurrency: 4,
});
// ✅ Worker: stable, production-ready, same functionality
const worker = new Worker('queue', async (job) => {
// same logic from your processor.ts
return result;
}, { embedded: true, concurrency: 4 });

If you must use SandboxedWorker:

  • Pin your Bun version, behavior varies across releases
  • Use graceful shutdown (await worker.stop()) instead of force termination
  • Use longer timeout values to avoid frequent terminations
  • Monitor memory usage closely

These issues will be resolved when Bun stabilizes their Worker API.

ErrorCauseSolution
Command timeoutWorker missing embedded: trueAdd embedded: true to Worker options
SQLITE_BUSYDatabase lockedUse single writer
SQLITE_FULLDisk fullFree disk space
ECONNREFUSEDServer not runningStart server or use embedded mode
ETIMEDOUTNetwork issueCheck connectivity
Job not foundAlready completed/removedCheck job lifecycle
Segmentation faultBun Worker termination bugUse graceful shutdown, see above

The server logs to stdout. Switch to structured JSON logs for easier filtering:

Terminal window
# Server mode (structured logs)
LOG_FORMAT=json bunqueue start
# Pipe to a file if you want persistent logs
LOG_FORMAT=json bunqueue start >> /var/log/bunqueue.log 2>&1

If these solutions don’t help:

  1. Check GitHub Issues
  2. Search Discussions
  3. Open a new issue with:
    • bunqueue version
    • Bun version
    • OS and hardware
    • Error message and stack trace
    • Minimal reproduction code