go-sql-driver/mysql · error

invalid dbname %q: %w

Error message

invalid dbname %q: %w

What it means

After isolating the database-name segment (between '/' and '?'), ParseDSN runs url.PathUnescape on it. If the segment contains malformed percent-encoding (e.g. '%ZZ', a lone '%' with no hex digits, or a truncated '%2'), PathUnescape fails and the driver wraps the underlying error as 'invalid dbname %q: %w' at dsn.go:465.

Source

Thrown at dsn.go:465

					}
				}
				cfg.Net = dsn[j+1 : k]
			}

			// dbname[?param1=value1&...&paramN=valueN]
			// Find the first '?' in dsn[i+1:]
			for j = i + 1; j < len(dsn); j++ {
				if dsn[j] == '?' {
					if err = parseDSNParams(cfg, dsn[j+1:]); err != nil {
						return
					}
					break
				}
			}

			dbname := dsn[i+1 : j]
			if cfg.DBName, err = url.PathUnescape(dbname); err != nil {
				return nil, fmt.Errorf("invalid dbname %q: %w", dbname, err)
			}

			break
		}
	}

	if !foundSlash && len(dsn) > 0 {
		return nil, errInvalidDSNNoSlash
	}

	if err = cfg.normalize(); err != nil {
		return nil, err
	}
	return
}

// parseDSNParams parses the DSN "query string"
// Values must be url.QueryEscape'ed

View on GitHub (pinned to c426bd9379)

Solutions

  1. URL-encode the database name with url.PathEscape when constructing the DSN.
  2. If the name genuinely contains '%', encode it as '%25'.
  3. Set cfg.DBName directly on a *mysql.Config and open via mysql.NewConnector(cfg) to bypass DSN parsing entirely.

Example fix

// before
dsn := fmt.Sprintf("user@tcp(host:3306)/%s", dbname) // dbname has '%'
// after
dsn := fmt.Sprintf("user@tcp(host:3306)/%s", url.PathEscape(dbname))
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the dbname segment round-trips through PathUnescape.
func validDBNameSegment(seg string) bool {
    _, err := url.PathUnescape(seg)
    return err == nil
}

Try / catch

if _, err := mysql.ParseDSN(dsn); err != nil {
    var ue *url.EscapeError
    if errors.As(err, &ue) || strings.Contains(err.Error(), "invalid dbname") {
        // re-encode the dbname with url.PathEscape and rebuild
    }
}

Prevention

When it happens

Trigger: A DSN like 'user@tcp(host:3306)/my%ZZdb' or 'user@tcp(host:3306)/db%' where the dbname portion is not valid percent-encoding; a literal '%' in the name not encoded as '%25'.

Common situations: A database name containing a literal '%' or other special char that someone half-escaped; a templating system injected a raw symbol; URL-fragment accidentally included.

Related errors


AI-assisted analysis of go-sql-driver/mysql@c426bd9379 (2026-08-04). Data as JSON: /data/errors/6caa65aeb686b798.json. Report an issue: GitHub.