ory/hydra · error
invalid DSN: empty scheme
Error message
invalid DSN: empty scheme
What it means
After cutting a DSN on '://', ExtractSchemeFromDSN checks that the part before the separator is non-empty. A string like ':///path/db' has a separator but no scheme, so the database driver still cannot be identified and the function returns this error.
Source
Thrown at oryx/sqlxx/sqlxx.go:90
func OnConflictDoNothing(dialect string, columnNoop string) string {
if dialect == "mysql" {
return fmt.Sprintf(" ON DUPLICATE KEY UPDATE `%s` = `%s` ", columnNoop, columnNoop)
} else {
return ` ON CONFLICT DO NOTHING `
}
}
// ExtractSchemeFromDSN returns the scheme (e.g. `mysql`, `postgres`, etc) component in a DSN string,
// as well as the remaining part of the DSN after the scheme separator.
// It is an error to not have a scheme present.
// This makes sense in the context of a DSN to be able to identify which database is in use.
func ExtractSchemeFromDSN(dsn string) (string, string, error) {
scheme, afterSchemeSeparator, schemeSeparatorFound := strings.Cut(dsn, "://")
if !schemeSeparatorFound {
return "", "", errors.New("invalid DSN: missing scheme separator")
}
if scheme == "" {
return "", "", errors.New("invalid DSN: empty scheme")
}
return scheme, afterSchemeSeparator, nil
}
// ExtractDbNameFromDSN returns the database name component in a DSN string.
func ExtractDbNameFromDSN(dsn string) (string, error) {
_, afterScheme, err := ExtractSchemeFromDSN(dsn)
if err != nil {
return "", err
}
_, afterSlash, slashFound := strings.Cut(afterScheme, "/")
if !slashFound {
return "", nil
}
dbName, _, _ := strings.Cut(afterSlash, "?")View on GitHub (pinned to 4174065ffb)
Solutions
- Ensure the scheme (postgres, mysql, sqlite, etc.) precedes '://' in the DSN
- Re-check the code path building the DSN string so the scheme is always prepended
- Log or validate the full DSN (redacted) at configuration load time
- Use package-provided constructors or constants for DSN schemes instead of manual strings
Example fix
// before dsn := "///var/lib/db.sqlite3" // after dsn := "sqlite:///var/lib/db.sqlite3"
Defensive patterns
Strategy: validation
Validate before calling
scheme, _, ok := strings.Cut(dsn, "://")
if !ok || scheme == "" {
return fmt.Errorf("DSN %q has an empty scheme", redact(dsn))
} Type guard
func dsnSchemePresent(dsn string) bool {
scheme, _, ok := strings.Cut(dsn, "://")
return ok && scheme != ""
} Try / catch
scheme, rest, err := sqlxx.ExtractSchemeFromDSN(dsn)
if err != nil {
return nil, fmt.Errorf("invalid DSN scheme: %w", err)
} Prevention
- Build DSNs with fmt.Sprintf("%s://%s", scheme, rest) so the scheme is never dropped
- Never strip the scheme when reassembling parsed URLs into DSNs
- Sanity-check scheme emptiness when accepting DSNs from user input
When it happens
Trigger: Calling ExtractSchemeFromDSN (or its callers SQLiteDirFromDSN, ExtractDbNameFromDSN, ReplaceSchemeInDSN, DSNRedacted) with a DSN starting with '://' or with an empty scheme before '://', e.g. ':///var/lib/db.sqlite3'.
Common situations: String concatenation or template interpolation that dropped the scheme prefix (e.g. fmt.Sprintf("://%s", host)); env var values where the scheme portion was deleted during editing; URL parsing that stripped the scheme before reassembling the DSN.
Related errors
- invalid DSN: missing scheme separator
- The DSN connection string looks like a SQLite connection, bu
- unsupported DSN type
- cookiex: purpose must be non-empty and must not contain a pi
- invalid JWK key
AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03).
Data as JSON: /api/errors/a27a1aac7be60ebd.
Report an issue: GitHub.