juicedata/juicefs · critical
unable to create engine: %s
Error message
unable to create engine: %s
What it means
JuiceFS builds a MySQL DSN (forcing transaction_isolation to repeatable-read) and calls xorm.NewEngine. If the driver cannot create an engine from the DSN (malformed DSN, bad params), this error wraps the underlying message. It is thrown before any network activity, so it almost always means the connection string itself is invalid.
Source
Thrown at pkg/meta/sql_mysql.go:67
}
return addr
}
func createMySQLEngine(dsn string) (*xorm.Engine, error) {
cfg, err := mysql.ParseDSN(recoveryMysqlPwd(dsn))
if err != nil {
return nil, err
}
if cfg.Params == nil {
cfg.Params = make(map[string]string)
}
var engine *xorm.Engine
for _, key := range []string{"transaction_isolation", "tx_isolation"} {
cfg.Params[key] = "'repeatable-read'"
engine, err = xorm.NewEngine("mysql", cfg.FormatDSN())
if err != nil {
return nil, fmt.Errorf("unable to create engine: %s", err)
}
if err = engine.Ping(); err == nil {
return engine, nil
}
_ = engine.Close()
delete(cfg.Params, key)
if !isUnknownTransactionIsolationErr(err, key) {
return nil, fmt.Errorf("ping database: %s", err)
}
}
return nil, fmt.Errorf("failed to set isolation level: %s", err)
}
func isUnknownTransactionIsolationErr(err error, key string) bool {View on GitHub (pinned to c9a67b23e8)
Solutions
- Check the inner driver message in the error for the exact DSN problem and fix the meta URL accordingly.
- URL-encode the password (and any special chars) in the meta URL, or pass the DSN with the password omitted and use env/my.cnf.
- Verify the DSN follows go-sql-driver format: user:password@tcp(host:port)/dbname?params.
- Test the same DSN with a small Go/CLI program using go-sql-driver to isolate whether it is a JuiceFS or driver issue.
Example fix
// before (bad DSN: special chars unescaped) juicefs format "mysql://root:p@ss!@tcp(1.2.3.4:3306)/jfs" vol // after (URL-encode password: p@ss! -> p%40ss%21) juicefs format "mysql://root:p%40ss%21@tcp(1.2.3.4:3306)/jfs" vol
Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(metaURL)
if err != nil || !strings.HasPrefix(u.Scheme, "mysql") {
return fmt.Errorf("meta URL must be mysql://user:pass@tcp(host:port)/db")
}
if pw, ok := u.User.Password(); ok && url.QueryEscape(pw) != pw {
return fmt.Errorf("password contains special characters: URL-encode it")
} Try / catch
if err := runMount(); err != nil && strings.Contains(err.Error(), "unable to create engine") {
log.Fatalf("invalid MySQL DSN: %v", err)
} Prevention
- URL-encode special characters in passwords
- Validate the DSN with the mysql client or a minimal go-sql-driver test before mounting
- Keep the DSN format user:pass@tcp(host:port)/db
When it happens
Trigger: `juicefs format mysql://...` / `mount mysql://...` with a DSN whose FormatDSN() output the go-sql-driver rejects — e.g. malformed `dsn` param, unescaped special characters in password, or invalid parameter syntax.
Common situations: Special characters (!@#) in the MySQL password not URL-encoded in the JuiceFS meta URL; typos like `mysql://user:pass@tcp(host:3306)/db` with missing tcp() wrapper; unsupported query params passed through.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- ping database: %s
- failed to set isolation level: %s
- unable to use data source %s: %s
- ping database: %s
- create table delegationToken: %s
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/79fb965be6a355ce.
Report an issue: GitHub.