hashicorp/nomad · error

failed to open BoltDB store: %w

Error message

failed to open BoltDB store: %w

What it means

MigrateToWAL wraps the error from raftboltdb.New when the source BoltDB store (raft.db) cannot be opened with a 5-second lock timeout. Typically the file is locked by a running server, missing, or corrupt.

Source

Thrown at helper/raftutil/migrate.go:85

	sendProgress(progress, "pre-flight checks passed")

	// Create marker file to detect if server accidentally starts during migration.
	if err := os.WriteFile(markerPath, []byte(time.Now().Format(time.RFC3339)), 0o600); err != nil {
		return fmt.Errorf("failed to create migration marker: %w", err)
	}
	defer os.Remove(markerPath) // Clean up marker on completion or failure.

	// Open the source BoltDB store.
	src, err := raftboltdb.New(raftboltdb.Options{
		Path: boltPath,
		BoltOptions: &bbolt.Options{
			Timeout: 5 * time.Second,
		},
		MsgpackUseNewTimeFormat: true,
	})
	if err != nil {
		return fmt.Errorf("failed to open BoltDB store: %w", err)
	}

	// Create the destination WAL store.
	if err := os.MkdirAll(walDir, 0o700); err != nil {
		src.Close()
		return fmt.Errorf("failed to create WAL directory: %w", err)
	}

	dst, err := raftwal.Open(walDir)
	if err != nil {
		src.Close()
		cleanupWAL(walDir)
		return fmt.Errorf("failed to open WAL store: %w", err)
	}

	// Copy logs.
	logProgress := make(chan string, 64)
	wg.Add(1)

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Stop the Nomad server process so the BoltDB file lock is released, then rerun
  2. Verify raft.db exists in the data dir (this tool migrates BoltDB to WAL; a WAL-only dir cannot be a source)
  3. Check permissions on raft.db; if corrupt, restore from backup or snapshot before migrating

Example fix

// before
systemctl start nomad && nomad-operator migrate-to-wal /var/nomad/data // lock contention
// after
systemctl stop nomad
# wait for lock release, then:
raftutil.MigrateToWAL("/var/nomad/data")
systemctl start nomad
Defensive patterns

Strategy: validation

Validate before calling

boltPath := filepath.Join(dataDir, "raft.db")
if _, err := os.Stat(boltPath); os.IsNotExist(err) {
    return fmt.Errorf("no raft.db at %s — nothing to migrate", boltPath)
}
if err := tryLockBoltDB(boltPath, 1*time.Second); err != nil {
    return fmt.Errorf("raft.db is locked — stop the nomad server first")
}

Try / catch

if err := raftutil.MigrateToWAL(dataDir); err != nil {
    if strings.Contains(err.Error(), "failed to open BoltDB store") && strings.Contains(err.Error(), "timeout") {
        return fmt.Errorf("another process holds raft.db — stop the nomad server: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling MigrateToWAL while the Nomad server still holds the BoltDB lock (times out after 5s), raft.db doesn't exist (NoBoltDB case), permissions deny access, or the DB file is corrupt.

Common situations: Forgetting to stop the Nomad server before migrating; pointing the tool at a WAL-only data dir with no raft.db; running as a user without read access to raft.db.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/a41dcec6f516d936. Report an issue: GitHub.