gofr-dev/gofr · error
failed to refresh MongoDB lock: lock lost or stolen
Error message
failed to refresh MongoDB lock: lock lost or stolen
What it means
errMongoLockRefreshFailed indicates the periodic heartbeat renewing the MongoDB migration lock failed because the lock document was lost or taken by another process. The migrator aborts rather than run migrations concurrently without exclusive ownership. It is raised by startRefresh during a long-running migration.
Source
Thrown at pkg/gofr/migration/mongo.go:13
package migration
import (
"context"
"errors"
"fmt"
"strings"
"time"
"gofr.dev/pkg/gofr/container"
)
var errMongoLockRefreshFailed = errors.New("failed to refresh MongoDB lock: lock lost or stolen")
type mongoDS struct {
container.Mongo
}
type mongoMigrator struct {
container.Mongo
migrator
testInterval time.Duration // Used for testing; if non-zero, overrides defaultRefresh
}
// apply initializes mongoMigrator using the Mongo interface.
func (ds mongoDS) apply(m migrator) migrator {
return mongoMigrator{
Mongo: ds.Mongo,
migrator: m,
}
}View on GitHub (pinned to 187eb24962)
Solutions
- Ensure only one migrator instance runs at a time (deployment serialization)
- Increase lock TTL or shorten migrations so renewals keep up
- Check MongoDB availability and the lock collection contents for stale/competing entries
- Re-run the migration once the lock is exclusively held again
Example fix
// before
// two pods both run migrations; second loses lock: failed to refresh MongoDB lock
// after
// serialize: k8s leader election or a single migration job
if !lockHeld(ctx, mongo) { return nil } // only migrate when lock is exclusively held Defensive patterns
Strategy: retry
Validate before calling
// ensure exclusive ownership before starting
var lockDoc bson.M
err := mongoCollection.FindOne(ctx, bson.M{"_id": "gofr_migrations_lock"}).Decode(&lockDoc)
if err == nil && lockDoc["owner"] != thisInstanceID {
return errors.New("lock held by another instance")
} Try / catch
err := migrator.Run(c)
if strings.Contains(err.Error(), "failed to refresh MongoDB lock") {
// abort migrating concurrently; verify no other instance, then retry
log.Error("lost mongo lock — another migrator may be running")
return err // do NOT continue migrations without the lock
} Prevention
- Run only one migrator instance per datastore (leader election / single job)
- Size lock TTL above worst-case migration duration with renewals
- Monitor MongoDB failovers during deploy windows
- Never ignore lock-refresh failures — concurrent migrations corrupt history
When it happens
Trigger: The background refresh loop fails to update the lock document in MongoDB: the document was deleted, lease expired, or another instance acquired it; the Mongo write matches no documents.
Common situations: Migration exceeds the lock TTL without renewal succeeding; two deployments migrating simultaneously; MongoDB failover mid-migration; manual cleanup of the lock collection.
Related errors
- failed to acquire migration lock
- failed to release migration lock
- mongo: %w
- elasticsearch: %w
- failed to record migration: %w
AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01).
Data as JSON: /api/errors/a4aea64a30abd56d.
Report an issue: GitHub.