charmbracelet/crush · error
failed to connect to database: %w
Error message
failed to connect to database: %w
What it means
runStats wraps any error from db.Connect, which opens (or fetches from a pool) the SQLite database at <dataDir>/crush.db, pings it, and applies migrations. This error means the database could not be opened or pinged: the data directory could not be created, the data-dir lock could not be acquired (another crush process holds it), the SQLite file is corrupt/unreadable, or the ping failed (bad driver state, cancelled context, file locked).
Source
Thrown at internal/cmd/stats.go:174
return fmt.Errorf("failed to gather stats from projects: %w", err)
}
default:
cfg, err := config.Init("", dataDir, false)
if err != nil {
return fmt.Errorf("failed to initialize config: %w", err)
}
if dataDir == "" {
dataDir = cfg.Config().Options.DataDirectory
}
if shouldEnableMetrics(cfg.Config()) {
event.Init()
}
event.StatsViewed()
conn, err := db.Connect(ctx, dataDir)
if err != nil {
return fmt.Errorf("failed to connect to database: %w", err)
}
defer conn.Close()
stats, err := gatherStats(ctx, conn)
if err != nil {
return fmt.Errorf("failed to gather stats: %w", err)
}
projectStats = []ProjectStats{{ProjectPath: "", Stats: stats}}
}
if len(projectStats) == 0 {
return fmt.Errorf("no data available: no projects found")
}
// Merge stats from all projects.
mergedStats := mergeStats(projectStats)
View on GitHub (pinned to 7944b8e522)
Solutions
- Check no other crush process is running against the same data dir (lock contention) and that <dataDir> is writable: ls -ld "$HOME/.local/share/crush".
- Inspect crush.db integrity with `sqlite3 crush.db 'PRAGMA integrity_check;'`; restore from backup or remove corrupted crush.db (and -wal/-shm) if acceptable.
- Verify env vars controlling the data dir (XDG_DATA_HOME, HOME) point to a writable directory; unset overrides or fix the path.
- If migrations or lock logs appear in stderr, read the wrapped %w cause shown by the error and address it specifically.
- Re-run the command; transient ping/IO failures (network home dirs, EFS/NFS) may resolve on retry.
Example fix
// before
conn, err := db.Connect(ctx, dataDir)
if err != nil {
return fmt.Errorf("failed to connect to database: %w", err)
}
// after
if dataDir == "" {
dataDir = defaultDataDir() // fall back to the standard data dir
}
conn, err := db.Connect(ctx, dataDir)
if err != nil {
var lockErr *db.DataDirLockError
if errors.As(err, &lockErr) {
return fmt.Errorf("another crush process is using %s; close it and retry", dataDir)
}
return fmt.Errorf("failed to connect to database: %w", err)
} Defensive patterns
Strategy: validation
Validate before calling
if info, err := os.Stat(filepath.Join(dataDir, "crush.db")); err == nil && info.Size() == 0 {
return fmt.Errorf("database file %s is empty/corrupt", dataDir)
}
if err := unix.Flock(lockFile, unix.LOCK_EX|unix.LOCK_NB); err != nil {
return fmt.Errorf("another crush instance holds the data dir")
} Try / catch
conn, err := db.Connect(ctx, dataDir)
if err != nil {
var lockErr *fs.PathError
if errors.As(err, &lockErr) {
return fmt.Errorf("data dir unusable (%s): %w", dataDir, err)
}
return err
} Prevention
- Keep the data dir on a local writable filesystem (not NFS) so SQLite locks and pings work.
- Close other crush instances before running stats against the same data dir.
- Back up crush.db together with its -wal and -shm files.
- Verify HOME/XDG_DATA_HOME before invoking the command.
When it happens
Trigger: Running `crush stats` where: (1) the data dir path is invalid or permissions deny os.MkdirAll; (2) another crush process holds the data-dir lock (WithDataDirLock); (3) crush.db is corrupted (e.g. SQLITE_NOTADB from prior WAL desync) or truncated; (4) the context is cancelled or the filesystem disallows opening/writing crush.db; (5) dataDir resolved to empty (db.Connect returns "data.dir is not set").
Common situations: Running stats while another crush instance is open on the same data dir; running with XDG_DATA_HOME/CRUSH_DATA pointed at a read-only or nonexistent mount; copying a crush.db without its -wal/-shm files causing SQLITE_NOTADB; disk full; running in a sandbox with restricted HOME.
Related errors
- failed to connect to database: %w
- failed to get session: %w
- error creating file history: %w
- failed to gather stats: %w
- get total stats: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/ece7dc22b0075ec0.
Report an issue: GitHub.