ory/hydra · error
invalid DSN: missing scheme separator
Error message
invalid DSN: missing scheme separator
What it means
ExtractSchemeFromDSN splits a DSN on the '://' separator and errors when no scheme is present. A DSN like 'postgres://...' yields scheme 'postgres'; a bare 'mydbhost/db' fails because the database type cannot be identified. This guard keeps downstream parsing from misinterpreting the DSN.
Source
Thrown at oryx/sqlxx/sqlxx.go:87
return strings.Join(statements, ", ")
}
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 "", nilView on GitHub (pinned to 4174065ffb)
Solutions
- Prefix the DSN with its proper scheme, e.g. 'postgres://' or 'sqlite://'
- Check the environment variable / config key supplying the DSN for a missing scheme
- Validate DSNs at startup with ExtractSchemeFromDSN and fail fast with a clear message
- If a file path is intended for SQLite, use the 'sqlite://' scheme followed by the path
Example fix
// before dsn := "localhost:5432/mydb" // after dsn := "postgres://localhost:5432/mydb"
Defensive patterns
Strategy: validation
Validate before calling
if !strings.Contains(dsn, "://") {
return fmt.Errorf("DSN %q must include a scheme, e.g. postgres://...", redact(dsn))
} Type guard
func hasDSNScheme(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("bad DSN (missing scheme?): %w", err)
} Prevention
- Always store full scheme-prefixed DSNs in env/config (e.g. postgres://, sqlite://)
- Validate DSNs at startup, not at first query time
- Don't pass bare hostnames or file paths where a DSN is expected
When it happens
Trigger: Calling ExtractSchemeFromDSN (directly or via SQLiteDirFromDSN, ExtractDbNameFromDSN, ReplaceSchemeInDSN, DSNRedacted) with a DSN string that lacks '://', e.g. 'sqlite:///path/db' is fine but 'localhost:5432/db' or a bare file path is not.
Common situations: Env vars (DSN/DB_URL) set to a hostname or file path without a scheme; config values migrated from tools that accept scheme-less connection strings; shell quoting stripping part of the URL; accidentally passing a database name instead of a full DSN.
Related errors
- invalid DSN: empty scheme
- 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/0fced857ea6eabe5.
Report an issue: GitHub.