dgraph-io/badger · error

File %s already exists

Error message

File %s already exists

What it means

newMemTable creates the next memtable WAL file; this error is returned when a file with the name that the new memtable would use (based on db.nextMemFid) already exists on disk. Normally the rotate path expects the file to not exist, so an existing file at that id indicates out-of-sync fid state or leftover files.

Source

Thrown at memtable.go:148

	if lerr == z.NewFile {
		return mt, lerr
	}
	err := mt.UpdateSkipList()
	return mt, y.Wrapf(err, "while updating skiplist")
}

func (db *DB) newMemTable() (*memTable, error) {
	mt, err := db.openMemTable(db.nextMemFid, os.O_CREATE|os.O_RDWR)
	if err == z.NewFile {
		db.nextMemFid++
		return mt, nil
	}

	if err != nil {
		db.opt.Errorf("Got error: %v for id: %d\n", err, db.nextMemFid)
		return nil, y.Wrapf(err, "newMemTable")
	}
	return nil, fmt.Errorf("File %s already exists", mt.wal.Fd.Name())
}

func (db *DB) mtFilePath(fid int) string {
	return filepath.Join(db.opt.Dir, fmt.Sprintf("%05d%s", fid, memFileExt))
}

func (mt *memTable) SyncWAL() error {
	return mt.wal.Sync()
}

func (mt *memTable) isFull() bool {
	if mt.sl.MemSize() >= mt.opt.MemTableSize {
		return true
	}
	if mt.opt.InMemory {
		// InMemory mode doesn't have any WAL.
		return false
	}

View on GitHub (pinned to 2a001d466f)

Solutions

  1. Stop all processes using the directory; ensure only one badger instance opens it
  2. Compare db.nextMemFid against existing %05d.clog files; remove stale leftover WAL files that were never fully committed (after confirming they're not referenced in MANIFEST)
  3. Restore the full consistent backup set of files rather than a partial copy
  4. Rebuild the DB (replay from backup or re-ingest) if the directory state is inconsistent

Example fix

// before: two processes on same dir
//   db1, _ := badger.Open(opt) // in service A
//   db2, _ := badger.Open(opt) // in service B -> 'File 000005.clog already exists'
// after: single owner, or a lock/coordination layer
if !acquiredDirLock(dir) {
    return errors.New("another badger instance owns this directory")
}
Defensive patterns

Strategy: validation

Validate before calling

// before opening, ensure no competing instance and that next-fid collisions are unlikely:
files, _ := os.ReadDir(dir)
ids := map[int]bool{}
for _, f := range files {
    var id int
    if n, err := fmt.Sscanf(f.Name(), "%05d", &id); err == nil && n == 1 {
        ids[id] = true
    }
}
_ = ids // investigate gaps/leftovers inconsistent with MANIFEST before open

Type guard

func singleOwner(dir string) bool {
    return os.Mkdir(filepath.Join(dir, ".lock"), 0o600) == nil // O_EXCL-style lock dir
}

Try / catch

db, err := badger.Open(opt)
if err != nil && strings.Contains(err.Error(), "already exists") {
    return fmt.Errorf("badger dir %s may be in use by another process or has stale WAL files: %w", opt.Dir, err)
}

Prevention

When it happens

Trigger: Memtable rotation via ensureRoomForWrite, dropAll, DropPrefix, or Open when a WAL file with the next memtable fid already exists in the directory (e.g. crash leftovers, manually added files, or fid counters reset while old files remain).

Common situations: Restoring a subset of files into the data dir so ids collide; running two badger instances against the same directory; older/patched builds whose fid numbering differs from files left on disk.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


AI-assisted analysis of dgraph-io/badger@2a001d466f (2026-09-05). Data as JSON: /api/errors/7485c8ad4da5db13. Report an issue: GitHub.