crowdsecurity/crowdsec · error
unable to set perms on %s: %w
Error message
unable to set perms on %s: %w
What it means
After creating the SQLite file, NewClient calls setFilePerm(db_path, 0640) and wraps any failure as `unable to set perms on <path>`. On Unix this is os.Chmod/chown-style enforcement; on Windows permission semantics differ, which is why the code always attempts it. Startup aborts on failure.
Source
Thrown at pkg/database/database.go:94
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)
if err != nil {
return nil, fmt.Errorf("failed opening connection to %s: %w", config.Type, err)
}
client = ent.NewClient(ent.Driver(drv), entOpt)
if config.LogLevel >= log.DebugLevel {
logger.Debugf("Enabling request debug")
View on GitHub (pinned to 909b515798)
Solutions
- chown the database file and its directory to the user crowdsec runs as (sudo chown crowdsec:crowdsec /var/lib/crowdsec/data/crowdsec.db)
- Remove immutable attributes (chattr -i) or move the data dir off restricted filesystems
- Delete the pre-existing file (backup first) so it's recreated by the correct user
- Check mount options (read-only) and MAC-policy denials
Example fix
// before -rw------- root root /var/lib/crowdsec/data/crowdsec.db # created by sudo run // after sudo chown crowdsec:crowdsec /var/lib/crowdsec/data/crowdsec.db sudo chmod 640 /var/lib/crowdsec/data/crowdsec.db
Defensive patterns
Strategy: validation
Validate before calling
info, err := os.Stat(dbPath)
if err == nil && info.Mode().Perm()&0o200 == 0 {
log.Fatalf("db file not writable by %s", os.Geteuid())
} Prevention
- Always run crowdsec as one consistent user; avoid mixing sudo and service runs
- Pre-set 0640 ownership/permissions in packaging/postinst
- Check for immutable flags or read-only mounts on the data dir
- On Windows, verify ACLs on the data directory
When it happens
Trigger: chmod fails because the process doesn't own the file (created previously by root, now running as the crowdsec user), read-only filesystem, or unsupported/failed permission operation on exotic filesystems (Windows ACLs, FUSE).
Common situations: First run executed with sudo and later runs as service user who can't chmod a root-owned file; Docker volume with mismatched UID; immutable flag set on the file.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- failed to create SQLite database file %q: %w
- unable to generate a new random seed for JWT generation
- not enough entropy at random seed generation for JWT generat
- no configuration paths provided
- while getting process attributes: both plugin user and group
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/35ac7950c6542aa7.
Report an issue: GitHub.