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

  1. chown the database file and its directory to the user crowdsec runs as (sudo chown crowdsec:crowdsec /var/lib/crowdsec/data/crowdsec.db)
  2. Remove immutable attributes (chattr -i) or move the data dir off restricted filesystems
  3. Delete the pre-existing file (backup first) so it's recreated by the correct user
  4. 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

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


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/35ac7950c6542aa7. Report an issue: GitHub.