apache/answer · error

insert first version failed: %v

Error message

insert first version failed: %v

What it means

When no version row exists, GetCurrentDBVersion seeds &entity.Version{ID:1, VersionNumber:0}. If that INSERT fails, the error is wrapped as 'insert first version failed: %v', aborting migration bootstrap.

Source

Thrown at internal/migrations/migrations.go:133

func GetMigrations() []Migration {
	return migrations
}

// GetCurrentDBVersion returns the current db version
func GetCurrentDBVersion(engine *xorm.Engine) (int64, error) {
	if err := engine.Sync(new(entity.Version)); err != nil {
		return -1, fmt.Errorf("sync version failed: %v", err)
	}

	currentVersion := &entity.Version{ID: 1}
	has, err := engine.Get(currentVersion)
	if err != nil {
		return -1, fmt.Errorf("get first version failed: %v", err)
	}
	if !has {
		_, err := engine.InsertOne(&entity.Version{ID: 1, VersionNumber: 0})
		if err != nil {
			return -1, fmt.Errorf("insert first version failed: %v", err)
		}
		return 0, nil
	}
	return currentVersion.VersionNumber, nil
}

// ExpectedVersion returns the expected db version
func ExpectedVersion() int64 {
	return int64(minDBVersion + len(migrations))
}

// Migrate database to current version
func Migrate(debug bool, dbConf *data.Database, cacheConf *data.CacheConf, upgradeToSpecificVersion string) error {
	cache, cacheCleanup, err := data.NewCache(cacheConf)
	if err != nil {
		fmt.Println("new cache failed:", err.Error())
	}
	engine, err := data.NewDB(debug, dbConf)

View on GitHub (pinned to 3b9f137061)

Solutions

  1. Check the wrapped DB error for duplicate-key vs privilege issues
  2. Serialize migrations (single instance / advisory lock) so only one process seeds the row
  3. Grant INSERT privilege on the `version` table to the migration user
  4. Manually insert the ID=1, VersionNumber=0 row if permitted, then re-run

Example fix

// before
return -1, fmt.Errorf("insert first version failed: %v", err)
// after
return -1, fmt.Errorf("insert first version failed: %w", err)
Defensive patterns

Strategy: validation

Validate before calling

// pre-check whether the version row already exists to skip seeding
has, _ := engine.IsTableExist(&entity.Version{})
if has {
    n, _ := engine.SQL("SELECT COUNT(*) FROM version WHERE id=1").Count()
    if n > 0 { /* seeding will conflict — investigate concurrent runners */ }
}

Try / catch

if err := runMigrations(engine); err != nil {
    if strings.Contains(err.Error(), "insert first version failed") {
        log.Errorf("could not seed version row; check write privileges or concurrent migration: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: engine.InsertOne on a fresh database fails: version table lacks ID=1 row but INSERT is denied (read-only user, insufficient privileges), duplicate key from a concurrent migration, or DB write error.

Common situations: Two instances running Migrate concurrently against the same fresh DB; migration user granted SELECT but not INSERT; disk full or DB in read-only mode; reserved-word or column mismatch on insert.

Related errors


AI-assisted analysis of apache/answer@3b9f137061 (2026-09-05). Data as JSON: /api/errors/d2f765c67bac33dc. Report an issue: GitHub.