crowdsecurity/crowdsec · critical
failed to create SQLite database file %q: %w
Error message
failed to create SQLite database file %q: %w
What it means
NewClient pre-creates the SQLite file when db_config.type is sqlite and the path isn't :memory:. If os.OpenFile(O_CREATE|O_RDWR, 0600) cannot create/open the file, the error is wrapped with this message and client startup aborts. This runs only on first startup (file does not exist yet).
Source
Thrown at pkg/database/database.go:85
if config == nil {
return nil, errors.New("DB config is empty")
}
entLogger := logger.WithField("context", "ent")
entOpt := ent.Log(entLogger.Debug)
typ, dia, err := config.ConnectionDialect()
if err != nil {
return nil, err // unsupported database caught here
}
if config.Type == "sqlite" && config.DbPath != ":memory:" {
/*if it's the first startup, we want to touch and chmod file*/
if _, err = os.Stat(config.DbPath); os.IsNotExist(err) {
f, err := os.OpenFile(config.DbPath, os.O_CREATE|os.O_RDWR, 0o600)
if err != nil {
return nil, fmt.Errorf("failed to create SQLite database file %q: %w", config.DbPath, err)
}
if err := f.Close(); err != nil {
return nil, fmt.Errorf("failed to create SQLite database file %q: %w", config.DbPath, err)
}
}
// Always try to set permissions to simplify a bit the code for windows (as the permissions set by OpenFile will be garbage)
if err = setFilePerm(config.DbPath, 0o640); err != nil {
return nil, fmt.Errorf("unable to set perms on %s: %w", config.DbPath, err)
}
}
dbConnectionString, err := config.ConnectionString()
if err != nil {
return nil, fmt.Errorf("failed to generate DB connection string: %w", err)
}
drv, err := getEntDriver(typ, dia, dbConnectionString, config)View on GitHub (pinned to 909b515798)
Solutions
- Check that the directory containing db_path exists and is writable by the crowdsec user (mkdir -p / chown)
- Verify db_path in the YAML points to a file path, not a directory, and is not :memory:-typoed
- Check for read-only mounts or MAC-policy (SELinux/AppArmor) denials in audit logs
- Run crowdsec as a user with write access to the data dir
Example fix
// before (crowdsec.yaml) db_config: type: sqlite db_path: /var/lib/crowdsec/data/crowdsec.db # dir missing // after sudo mkdir -p /var/lib/crowdsec/data && sudo chown crowdsec:crowdsec /var/lib/crowdsec/data
Defensive patterns
Strategy: validation
Validate before calling
// before starting crowdsec
path := "/var/lib/crowdsec/data/crowdsec.db"
dir := filepath.Dir(path)
if info, err := os.Stat(dir); err != nil || !info.IsDir() {
os.MkdirAll(dir, 0o750)
}
f, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, 0o600)
if err != nil { log.Fatalf("db path not writable: %v", err) }
f.Close() Prevention
- Pre-create the data directory and chown it to the service user
- Never point db_path at a directory or read-only mount
- Check SELinux/AppArmor audit logs on permission denials
- Verify config YAML db_path on fresh installs
When it happens
Trigger: The parent directory does not exist or is not writable, the path points to a directory, permission is denied (wrong user, read-only filesystem, sandboxed dir), or the path is invalid for the OS.
Common situations: db_config.db_path in /etc/crowdsec/config.yaml pointing at a non-existent directory or a path the crowdsec user can't write (e.g. running under systemd with a different User=); Docker volume mounted read-only; SELinux/AppArmor denial.
Understand the failure class
Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.
Related errors
- unable to set perms on %s: %w
- while checking acquisition_path: %w
- while creating directories for %s: %w
- while dumping console config to %s: %w
- while opening %s: %w
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/47d5e8d03a6da9b1.
Report an issue: GitHub.