apache/answer · error

sync version failed: %v

Error message

sync version failed: %v

What it means

GetCurrentDBVersion syncs the entity.Version table with xorm before reading the schema version. If engine.Sync fails (it cannot create/alter the version table), the error is wrapped as 'sync version failed: %v' and Migrate aborts with -1.

Source

Thrown at internal/migrations/migrations.go:122

	NewMigration("v1.5.1", "add plugin kv storage", addPluginKVStorage, true),
	NewMigration("v1.6.0", "move user config to interface", moveUserConfigToInterface, true),
	NewMigration("v1.7.0", "add optional tags", addOptionalTags, true),
	NewMigration("v1.7.2", "expand avatar column length", expandAvatarColumnLength, false),
	NewMigration("v1.8.0", "change admin menu", updateAdminMenuSettings, true),
	NewMigration("v1.8.1", "ai feat", aiFeat, true),
	NewMigration("v2.0.1", "change avatar type to text", updateAvatarType, false),
	NewMigration("v2.0.2", "add reasoning content to ai conversation record", addAIConversationReasoningContent, false),
	NewMigration("v2.0.3", "add require email verification login setting", addRequireEmailVerification, true),
}

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

View on GitHub (pinned to 3b9f137061)

Solutions

  1. Check the underlying DB error after 'sync version failed:'
  2. Run migrations with a user that has CREATE/ALTER privileges
  3. Verify network connectivity to the database and that it accepts DDL
  4. Manually inspect the `version` table for conflicts with entity.Version fields

Example fix

// before
if err := engine.Sync(new(entity.Version)); err != nil {
    return -1, fmt.Errorf("sync version failed: %v", err)
}
// after
if err := engine.Sync(new(entity.Version)); err != nil {
    return -1, fmt.Errorf("sync version failed: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check DDL capability
if _, err := engine.Exec("SELECT 1"); err != nil {
    return fmt.Errorf("db not ready: %w", err)
}

Try / catch

version, err := migrations.GetCurrentDBVersion(engine)
if err != nil {
    if strings.HasPrefix(err.Error(), "sync version failed") {
        log.Errorf("cannot sync version table, check DDL privileges: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: engine.Sync(new(entity.Version)) returns an error: DB unreachable, insufficient DDL privileges to create/alter table `version`, table schema conflicts xorm cannot reconcile, or context timeout.

Common situations: First bootstrap on a fresh database where DDL is denied; production DB with read-only migration user; xorm tag changes on entity.Version conflicting with existing table; transient connection drops.

Related errors


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