crowdsecurity/crowdsec · error

failed opening connection to %s: %w

Error message

failed opening connection to %s: %w

What it means

NewClient wraps the error from getEntDriver when the ent ORM driver cannot open a connection using the generated DSN. Unlike error 960, the connection string was built but the actual driver open failed — usually wrong credentials, unreachable host, or bad DSN syntax for the DB type.

Source

Thrown at pkg/database/database.go:105

			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")

		client = client.Debug()
	}

	if err = client.Schema.Create(ctx, dropLegacyIndex("decisions", "decision_value")); err != nil {
		return nil, fmt.Errorf("failed creating schema resources: %w", err)
	}

	return &Client{
		Ent:              client,
		Log:              logger,
		Type:             config.Type,

View on GitHub (pinned to 909b515798)

Solutions

  1. Check the wrapped inner error for driver specifics (auth failed, unknown host, dialect error).
  2. Verify the DB server is reachable: test with the mysql/psql client using the same host/port/credentials.
  3. For sqlite, confirm the db_path exists and is writable by the crowdsec process.
  4. Add/adjust driver options like sslmode for postgres or timeout params in the config.

Example fix

// before (postgres w/o TLS setup)
db_config:
  type: postgres
  host: db.internal
  sslmode: verify-full
// after
db_config:
  type: postgres
  host: db.internal
  sslmode: require
Defensive patterns

Strategy: retry

Validate before calling

// pre-check reachability
conn, err := net.DialTimeout("tcp", net.JoinHostPort(cfg.Host, cfg.Port), 3*time.Second)
if err != nil {
    return fmt.Errorf("db %s:%s unreachable: %w", cfg.Host, cfg.Port, err)
}
conn.Close()

Try / catch

drv/open errors are wrapped; retry with backoff only for transient errors:
for i := 0; i < 5; i++ {
    client, err = database.NewClient(ctx, cfg)
    if err == nil || !isTransient(err) { break }
    time.Sleep(time.Duration(1<<i) * time.Second)
}

Prevention

When it happens

Trigger: database.NewClient with a mysql/postgres server that is down or refusing auth; sqlite file path that cannot be opened (locked, on read-only FS); malformed connection string parameters rejected by the driver.

Common situations: MySQL container not started before crowdsec; wrong db password after rotation; connecting to postgres over SSL without sslmode configured; sqlite db on an NFS/immutable mount.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


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