juanfont/headscale · error · errDatabaseNotSupported

database of type %s is not supported: %w

Error message

database of type %s is not supported: %w

What it means

openDB switches on cfg.Database.Type and only 'sqlite' and 'postgres' are implemented; anything else falls through to this terminal error wrapping errDatabaseNotSupported. It is a configuration validation error, not a runtime fault.

Source

Thrown at hscontrol/db/db.go:1153

		db, err := gorm.Open(postgres.Open(dbString), &gorm.Config{
			Logger: dbLogger,
		})
		if err != nil {
			return nil, err
		}

		sqlDB, _ := db.DB()
		sqlDB.SetMaxIdleConns(cfg.Postgres.MaxIdleConnections)
		sqlDB.SetMaxOpenConns(cfg.Postgres.MaxOpenConnections)
		sqlDB.SetConnMaxIdleTime(
			time.Duration(cfg.Postgres.ConnMaxIdleTimeSecs) * time.Second,
		)

		return db, nil
	}

	return nil, fmt.Errorf(
		"database of type %s is not supported: %w",
		cfg.Type,
		errDatabaseNotSupported,
	)
}

func runMigrations(cfg types.DatabaseConfig, dbConn *gorm.DB, migrations *gormigrate.Gormigrate) error {
	if cfg.Type == types.DatabaseSqlite {
		// SQLite: Run the early migrations that GORM cannot handle safely with
		// foreign keys enabled (route and pre-auth-key automigrations) with FK
		// disabled, then run everything else with FK enabled.
		//
		// NO NEW MIGRATIONS SHOULD RUN WITH FK DISABLED. As of 2025-07-02, all
		// new migrations must run with foreign keys enabled via the
		// migrations.Migrate() call below.
		if err := dbConn.Exec("PRAGMA foreign_keys = OFF").Error; err != nil { //nolint:noinlineerr
			return fmt.Errorf("disabling foreign keys: %w", err)
		}

View on GitHub (pinned to 565fd254d0)

Solutions

  1. Set db.type to exactly sqlite or postgres in config.yaml (or the HS_DB_TYPE env var).
  2. Check for stray whitespace/quotes around the type value.
  3. headscale does not support MySQL/MariaDB — choose postgres if sqlite is insufficient.

Example fix

// before (config.yaml)
db:
  type: mysql

// after
db:
  type: sqlite
  sqlite:
    path: /var/lib/headscale/db.sqlite
Defensive patterns

Strategy: validation

Validate before calling

// Validate config before startup
type dbCfg struct{ Type string }
func validDbType(t string) bool {
    switch strings.ToLower(strings.TrimSpace(t)) {
    case "sqlite", "postgres":
        return true
    }
    return false
}

Try / catch

// Fail fast on unsupported type; there is no fallback. Correct db.type in
// config.yaml / HS_DB_TYPE and restart.

Prevention

When it happens

Trigger: Setting db.type to a value other than sqlite/postgres in config.yaml (e.g. 'mysql', 'postgres16', trailing whitespace, or a typo like 'sqllite').

Common situations: Copy-pasted config from another tool expecting MySQL support; case or spelling mistakes in the type string; env var overrides (HS_DB_TYPE) with a wrong value.

Related errors


AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15). Data as JSON: /api/errors/c233f9e5e8d8cb95. Report an issue: GitHub.