iflytek/astron-agent · error

mysql dsn is nil

Error message

mysql dsn is nil

What it means

ensureMySQLDatabase receives the parsed go-sql-driver *mysql.Config and guards against a nil pointer before it clones the DSN to run admin (database-creating) statements. A nil parsedDsn means the DSN parse step upstream produced no config object at all, so the function cannot proceed.

Solutions

  1. In buildMysql, check the error from mysql.ParseDSN before using the returned config and return the parse error instead of continuing.
  2. Ensure the DSN string built in parseMysqlConfig is non-empty and well-formed before parsing.
  3. Add a defensive nil check/log where the *mysql.Config originates so the nil never propagates.
  4. Write a unit test for buildMysql covering the empty-DSN path.

Example fix

// before
parsedDsn, _ := mysql.ParseDSN(dsn)
if err := ensureMySQLDatabase(parsedDsn); err != nil {
    return nil, err
}

// after
parsedDsn, err := mysql.ParseDSN(dsn)
if err != nil {
    return nil, fmt.Errorf("parse mysql dsn: %w", err)
}
if err := ensureMySQLDatabase(parsedDsn); err != nil {
    return nil, err
}
Defensive patterns

Strategy: type-guard

Validate before calling

if parsedDsn == nil {
	return errors.New("mysql dsn parse failed before ensureMySQLDatabase")
}

Type guard

func dsnConfigIsValid(c *mysql.Config) bool { return c != nil && c.DBName != "" }

Try / catch

if err != nil {
	return fmt.Errorf("build mysql: %w", err)
}

Prevention

When it happens

Trigger: buildMysql calls ensureMySQLDatabase with the result of mysql.ParseDSN when that call returned nil (typically alongside a parse error that was mishandled or an empty DSN input).

Common situations: Programmer error where the ParseDSN error is ignored and nil is passed through; refactoring that changed the DSN construction and dropped the error check; calling ensureMySQLDatabase directly in tests with no config.

Related errors


AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12). Data as JSON: /api/errors/487a23974615d218. Report an issue: GitHub.

Appendix: source

Thrown at core/tenant/tools/database/database.go:114

	credentials config.TenantBootstrapCredentials,
) error {
	if err := runMigrations(client); err != nil {
		return err
	}
	if err := reconcileTenantBootstrap(client, credentials); err != nil {
		return err
	}
	log.Printf("tenant bootstrap credentials reconciled")
	return nil
}

func (db *Database) GetMysql() *sql.DB {
	return db.mysql
}

func ensureMySQLDatabase(parsedDsn *mysql.Config) error {
	if parsedDsn == nil {
		return errors.New("mysql dsn is nil")
	}
	if parsedDsn.DBName == "" {
		return errors.New("mysql database name is empty")
	}

	adminDsn := parsedDsn.Clone()
	dbName := adminDsn.DBName
	adminDsn.DBName = ""

	client, err := sql.Open("mysql", adminDsn.FormatDSN())
	if err != nil {
		return err
	}
	defer func() {
		_ = client.Close()
	}()

	if err := client.Ping(); err != nil {

View on GitHub (pinned to 5e758547a8)