gofr-dev/gofr · error

sql: %w

Error message

sql: %w

What it means

This error wraps any failure that occurs while querying the migrations table via SQL in the GoFr migration framework. getLastMigration issues `SELECT ... FROM gofr_migrations` (getLastSQLGoFrMigration) through the container's SQL datasource and scans the result into an int64. If the query or scan fails (missing table, connection failure, NULL value), the underlying driver error is wrapped with the `sql:` prefix so callers can identify the SQL migration stage.

Source

Thrown at pkg/gofr/migration/sql.go:88

func (d sqlMigrator) checkAndCreateMigrationTable(c *container.Container) error {
	if _, err := c.SQL.Exec(createSQLGoFrMigrationsTable); err != nil {
		return err
	}

	if _, err := c.SQL.Exec(createSQLGoFrMigrationLocksTable); err != nil {
		return err
	}

	return d.migrator.checkAndCreateMigrationTable(c)
}

func (d sqlMigrator) getLastMigration(c *container.Container) (int64, error) {
	var lastMigration int64

	err := c.SQL.QueryRowContext(context.Background(), getLastSQLGoFrMigration).Scan(&lastMigration)
	if err != nil {
		return -1, fmt.Errorf("sql: %w", err)
	}

	c.Debugf("SQL last migration fetched value is: %v", lastMigration)

	lm2, err := d.migrator.getLastMigration(c)
	if err != nil {
		return -1, err
	}

	return max(lastMigration, lm2), nil
}

func (d sqlMigrator) commitMigration(c *container.Container, data transactionData) error {
	if data.UsedDatasources[dsSQL] {
		dialect := c.SQL.Dialect()

		switch dialect {
		case mysql, sqlite:

View on GitHub (pinned to 187eb24962)

Solutions

  1. Verify the database is reachable and credentials/DSN in the container config are correct by testing a simple query.
  2. Run the migration setup so the gofr_migrations table exists (checkAndCreateMigrationTable runs before getLastMigration; confirm it succeeded).
  3. Inspect the wrapped driver error (%w) for the root cause (e.g. 'connection refused', 'no such table').
  4. Check network/firewall/proxy between the app and the SQL server.

Example fix

// before: migrations run against a fresh DB with no table and DB may be down
app.Migrate()
// after: pre-check connectivity and let migrations create the table
if err := sqlDB.Ping(); err != nil {
	log.Fatalf("database not reachable: %v", err)
}
app.Migrate()
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: check SQL connectivity before running migrations
if err := c.SQL.Ping(); err != nil {
	return fmt.Errorf("sql unavailable before migration: %w", err)
}

Type guard

var sqlDB *sql.DB
db, ok := c.SQL.(*sql.DB)
if !ok || db == nil {
	return errors.New("SQL datasource not configured")
}

Try / catch

last, err := migrator.getLastMigration(c)
if err != nil {
	var pathErr *net.OpError
	if errors.As(err, &pathErr) {
		// retry / fail fast with connection context
	}
	return fmt.Errorf("migration state lookup failed: %w", err)
}

Prevention

When it happens

Trigger: Calling Migration.Run/Migrate with a SQL migrator when c.SQL.QueryRowContext(...).Scan(&lastMigration) fails: database unreachable, credentials wrong, gofr_migrations table absent, or the scanned column is NULL/non-numeric.

Common situations: Fresh database where migrations table was never created; SQL server down or wrong DSN in config; network/firewall blocking the DB; a migration row with NULL version value.

Understand the failure class

Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.

Related errors


AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01). Data as JSON: /api/errors/e133dd651f8dadf4. Report an issue: GitHub.