cloudreve/cloudreve · error
failed to start transaction: %w
Error message
failed to start transaction: %w
What it means
Returned when m.v4client.Tx(context.Background()) fails to open the batch transaction on the v4 target (application/migrator/user.go:44-47). ent returns a nil *Tx with the error; as with the share migrator, the following _ = tx.Rollback() runs on that nil Tx and ent's Tx.Rollback dereferences tx.config (ent/tx.go:148-149), so this path usually surfaces as a nil-pointer panic rather than the wrapped 'failed to start transaction' error.
Source
Thrown at application/migrator/user.go:45
for {
m.l.Info("Migrating users with offset %d", offset)
var users []model.User
if err := model.DB.Limit(batchSize).Offset(offset).Find(&users).Error; err != nil {
return fmt.Errorf("failed to list v3 users: %w", err)
}
if len(users) == 0 {
if m.dep.ConfigProvider().Database().Type == conf.PostgresDB {
m.l.Info("Resetting user ID sequence for postgres...")
m.v4client.User.ExecContext(ctx, "SELECT SETVAL('users_id_seq', (SELECT MAX(id) FROM users))")
}
break
}
tx, err := m.v4client.Tx(context.Background())
if err != nil {
_ = tx.Rollback()
return fmt.Errorf("failed to start transaction: %w", err)
}
for _, u := range users {
userStatus := user.StatusActive
switch u.Status {
case model.Active:
userStatus = user.StatusActive
case model.NotActivicated:
userStatus = user.StatusInactive
case model.Baned:
userStatus = user.StatusManualBanned
case model.OveruseBaned:
userStatus = user.StatusSysBanned
}
setting := &types.UserSetting{
VersionRetention: true,
VersionRetentionMax: 10,View on GitHub (pinned to 20c95ad73f)
Solutions
- If you got a panic instead of this error string, the nil tx.Rollback() is the cause - resolve the underlying connection failure.
- Confirm v4 connectivity/credentials from the migration host.
- Free up connection slots (stop the v4 instance during migration) or raise max_connections.
- Patch out the _ = tx.Rollback() line so future failures return the real error.
Example fix
// before
tx, err := m.v4client.Tx(context.Background())
if err != nil {
_ = tx.Rollback() // tx is nil -> panic
return fmt.Errorf("failed to start transaction: %w", err)
}
// after
tx, err := m.v4client.Tx(context.Background())
if err != nil {
return fmt.Errorf("failed to start transaction: %w", err)
} Defensive patterns
Strategy: validation
Validate before calling
// Round-trip test before the loop
tx, err := v4client.Tx(context.Background())
if err != nil {
return fmt.Errorf("v4 DB cannot open transaction: %w", err)
}
_ = tx.Rollback() Type guard
if tx == nil && err != nil {
// ent failed to create the Tx; touching tx.Rollback() panics
return err
} Try / catch
tx, err := m.v4client.Tx(context.Background())
if err != nil {
// no Rollback call: tx is nil here
return fmt.Errorf("failed to start transaction: %w", err)
} Prevention
- Fix the nil-Rollback pattern in custom migrators: only Rollback a successfully created Tx.
- Ensure the v4 DB is up and connection headroom exists before user batches begin.
- Pre-flight a Tx/Rollback pair to surface connectivity issues early.
When it happens
Trigger: v4 DB down/unreachable; too many connections; missing transaction privilege; connect timeout from an exhausted pool; context canceled by an upstream shutdown.
Common situations: Starting user migration before the v4 database is ready; DB connection limits consumed by the app plus migration; wrong v4 DSN passed to the migrator; Kubernetes pod DNS not resolving the DB service.
Related errors
- failed to start transaction: %w
- failed to start transaction: %w
- failed to create group %q: %w
- failed creating schema resources: %w
- failed to create setting %q: %w
AI-assisted analysis of cloudreve/cloudreve@20c95ad73f (2026-08-16).
Data as JSON: /api/errors/30287455e6530af9.
Report an issue: GitHub.