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
- Check the wrapped DB error for duplicate-key vs privilege issues
- Serialize migrations (single instance / advisory lock) so only one process seeds the row
- Grant INSERT privilege on the `version` table to the migration user
- 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
- Run only one migration process at a time (lock or single instance)
- Grant INSERT privilege on the version table
- Ensure the DB is writable (not read-only / disk not full)
- Seed the version row manually only when its absence is confirmed
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
- insert site info failed: %w
- %s failed: %s
- sync version failed: %v
- get first version failed: %v
- get config failed: %w
AI-assisted analysis of apache/answer@3b9f137061 (2026-09-05).
Data as JSON: /api/errors/d2f765c67bac33dc.
Report an issue: GitHub.