golang-migrate/migrate · error
x-no-tx-wrap: %s
Error message
x-no-tx-wrap: %s
What it means
The sqlite driver's Open parses the x-no-tx-wrap URL query parameter as a boolean (strconv.ParseBool) to decide whether migrations run outside a transaction. A present-but-invalid value causes Open to return fmt.Errorf("x-no-tx-wrap: %s", err), embedding the parse error and offending value. Valid values are Go's recognized booleans: 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False.
Source
Thrown at database/sqlite/sqlite.go:112
}
dbfile := strings.Replace(migrate.FilterCustomQuery(purl).String(), "sqlite://", "", 1)
db, err := sql.Open("sqlite", dbfile)
if err != nil {
return nil, err
}
qv := purl.Query()
migrationsTable := qv.Get("x-migrations-table")
if len(migrationsTable) == 0 {
migrationsTable = DefaultMigrationsTable
}
noTxWrap := false
if v := qv.Get("x-no-tx-wrap"); v != "" {
noTxWrap, err = strconv.ParseBool(v)
if err != nil {
return nil, fmt.Errorf("x-no-tx-wrap: %s", err)
}
}
mx, err := WithInstance(db, &Config{
DatabaseName: purl.Path,
MigrationsTable: migrationsTable,
NoTxWrap: noTxWrap,
})
if err != nil {
return nil, err
}
return mx, nil
}
func (m *Sqlite) Close() error {
return m.db.Close()
}
View on GitHub (pinned to 01a9643f14)
Solutions
- Use a strconv.ParseBool-accepted value: true/TRUE/True/t/T/1 or false/FALSE/False/f/F/0.
- Omit x-no-tx-wrap entirely to keep the default transaction-wrapped behavior.
- Trim whitespace and quotes from the DSN before passing it to migrate.Open/sql.Open.
Example fix
// before dsn := "sqlite://data/app.db?x-no-tx-wrap=on" // parse error // after dsn := "sqlite://data/app.db?x-no-tx-wrap=1"
Defensive patterns
Strategy: validation
Validate before calling
if v := q.Get("x-no-tx-wrap"); v != "" {
if _, err := strconv.ParseBool(v); err != nil {
return fmt.Errorf("invalid x-no-tx-wrap %q: use 1/t/true or 0/f/false", v)
}
} Type guard
func validBoolParam(v string) bool {
_, err := strconv.ParseBool(v)
return err == nil
} Try / catch
d, err := sqlite.Open(dsn)
if err != nil {
if strings.HasPrefix(err.Error(), "x-no-tx-wrap:") {
return fmt.Errorf("fix DSN boolean param (allowed: 1,t,true,0,f,false): %w", err)
}
return err
} Prevention
- Only use Go-parseable booleans (1/t/true/0/f/false) in x-no-tx-wrap.
- Validate the DSN with url.ParseQuery before passing to Open.
- Trim whitespace/quotes from DSNs sourced from env vars or templates.
- Omit the parameter entirely when the default (tx-wrapped) behavior is wanted.
When it happens
Trigger: Opening with a URL like sqlite://app.db?x-no-tx-wrap=on (or "yes", "Y", " true") — the parameter is present and non-empty but strconv.ParseBool rejects it.
Common situations: Human-style booleans ("yes"/"on") in the DSN copied from other tools' docs; shell/env quoting or whitespace contaminating the connection string; templated DSNs where the flag value is substituted from a non-boolean config.
Related errors
AI-assisted analysis of golang-migrate/migrate@01a9643f14 (2026-09-02).
Data as JSON: /api/errors/dbc9e3975f84b30e.
Report an issue: GitHub.