argoproj/argo-workflows · error

failed to create upper/db session: %w

Error message

failed to create upper/db session: %w

What it means

Returned when upper/db's MySQL adapter (mysqladp.New) fails to wrap the already-opened *sql.DB into an upper/db session. The traced *sql.DB is closed before returning so connections are not leaked. This is a session-construction failure in the upper/db layer, not a TCP dial failure — the underlying *sql.DB was created successfully.

Source

Thrown at util/sqldb/sqldb.go:306

	}

	// Wrap the MySQL connector so Connect (dial + handshake read) is bounded by
	// connectTimeout, protecting against a half-open server the same way lib/pq's
	// connect_timeout protects PostgreSQL.
	connector, err := mysql.NewConnector(mysqlCfg)
	if err != nil {
		return nil, fmt.Errorf("failed to create mysql connector: %w", err)
	}
	wrapped := &timeoutConnector{Connector: connector, timeout: connectTimeout}

	// Create traced *sql.DB using otelsql
	sqlDB := otelsql.OpenDB(wrapped, otelSQLOptions(semconv.DBSystemNameMySQL, cfg.Database)...)

	// Wrap with upper/db
	session, err := mysqladp.New(sqlDB)
	if err != nil {
		sqlDB.Close()
		return nil, fmt.Errorf("failed to create upper/db session: %w", err)
	}

	session = ConfigureDBSession(session, persistPool)

	// this is needed to make MySQL run in a Golang-compatible UTF-8 character set.
	_, err = session.SQL().Exec("SET NAMES 'utf8mb4'")
	if err != nil {
		return nil, err
	}
	_, err = session.SQL().Exec("SET CHARACTER SET utf8mb4")
	if err != nil {
		return nil, err
	}
	return session, nil
}

// otelSQLOptions returns the common otelsql tracing options for a database connection.
func otelSQLOptions(systemName attribute.KeyValue, database string) []otelsql.Option {

View on GitHub (pinned to 35bff19146)

Solutions

  1. Read the wrapped error from upper/db's mysql adapter; check for nil sql.DB input in the calling path.
  2. Check the vendored upper/db versions (github.com/uptrace/updb / upper/db v4 adapter) for known incompatibilities and run make codegen/vendor update.
  3. Retry controller startup — if this persists on a stock build, file an issue with the wrapped error text.
  4. As a diagnostic, connect with the same DSN via a plain sql.Open to separate upper/db issues from driver issues.
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure the *sql.DB is usable before upper/db wrap
if sqlDB == nil { return errors.New("nil sql.DB for mysql session") }
if err := sqlDB.Ping(); err != nil { return fmt.Errorf("mysql unreachable: %w", err) }

Try / catch

session, err := CreateDBSessionWithCreds(ctx)
if err != nil && strings.Contains(err.Error(), "failed to create upper/db session") {
    logger.Error(ctx, "upper/db mysql adapter failed", err)
    return err
}

Prevention

When it happens

Trigger: createMySQLDBSessionWithCreds passes a valid *sql.DB to mysqladp.New, and upper/db rejects it (unexpected nil DB or adapter initialization error). Rare in practice since a non-nil *sql.DB from otelsql.OpenDB should always be acceptable.

Common situations: Version incompatibility between the vendored upper/db adapter and database/sql plumbing; nil deref from passing a nil *sql.DB in custom code paths; patched dependency builds.

Related errors


AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03). Data as JSON: /api/errors/d8bb05828697fd4a. Report an issue: GitHub.