nsqio/nsq · critical
cannot flock directory %s - %s (possibly in use by another i
Error message
cannot flock directory %s - %s (possibly in use by another instance of nsqd)
What it means
internal/dirlock wraps an exclusive, non-blocking flock (syscall.Flock with LOCK_EX|LOCK_NB) on the directory fd of nsqd's --data-path; Lock returns 'cannot flock directory %s - %s (possibly in use by another instance of nsqd)' when the flock syscall itself errors. Its purpose is to stop two nsqd processes from sharing one data directory and corrupting disk-backed queue state. The wrapped syscall error distinguishes the causes: EWOULDBLOCK means another holder exists; other errnos mean the filesystem does not support flock at all.
Source
Thrown at internal/dirlock/dirlock.go:31
dir string
f *os.File
}
func New(dir string) *DirLock {
return &DirLock{
dir: dir,
}
}
func (l *DirLock) Lock() error {
f, err := os.Open(l.dir)
if err != nil {
return err
}
l.f = f
err = syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
if err != nil {
return fmt.Errorf("cannot flock directory %s - %s (possibly in use by another instance of nsqd)", l.dir, err)
}
return nil
}
func (l *DirLock) Unlock() error {
err := syscall.Flock(int(l.f.Fd()), syscall.LOCK_UN)
closeErr := l.f.Close()
if err != nil {
return err
}
return closeErr
}
View on GitHub (pinned to 85cf10c09c)
Solutions
- Find and stop the other process: 'fuser -v <data-path>' / 'ps aux | grep nsqd' / 'lsof +D <data-path>', then start nsqd again.
- Give each nsqd instance its own --data-path (the standard fix for fleets and local parallel runs).
- Move the data path off network/FUSE filesystems onto local disk (ext4/xfs) — flock on a directory must be supported.
- If you truly need shared storage, do not share one dir between live nsqd processes; architect replication with nsqd nodes instead.
Example fix
# before: two instances, same dir nsqd --data-path=/var/lib/nsq ... # instance A running nsqd --data-path=/var/lib/nsq ... # instance B -> cannot flock directory ... # after: separate data paths (or stop the old instance first) nsqd --data-path=/var/lib/nsq-a ... nsqd --data-path=/var/lib/nsq-b ...
Defensive patterns
Strategy: validation
Validate before calling
// pre-start: assert no other nsqd holds the data dir and the fs supports flock
func canLockDataDir(dir string) error {
f, err := os.Open(dir)
if err != nil {
return err
}
defer f.Close()
if err := syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB); err != nil {
return fmt.Errorf("data dir %s busy or unsupported fs: %w", dir, err)
}
return syscall.Flock(int(f.Fd()), syscall.LOCK_UN)
} Try / catch
// orchestrators: catch startup failure and name the two causes
if err := startNsqd(cfg); err != nil && strings.Contains(err.Error(), "cannot flock directory") {
if errors.Is(err, syscall.EWOULDBLOCK) {
return errors.New("another nsqd owns this data-path; stop it or assign a new --data-path")
}
return errors.New("data-path filesystem does not support flock; use local disk")
} Prevention
- Give every nsqd a unique --data-path by construction (hostname suffix).
- Never place --data-path on NFS/FUSE mounts.
- Have init systems/executors stop the old instance before starting a replacement.
When it happens
Trigger: Starting a second nsqd with the same --data-path (EWOULDBLOCK/EAGAIN); or running the data path on a filesystem that cannot flock a directory: NFS without a lock manager, some network/FUSE mounts, older CIFS setups, or certain container volumes (EROFS/EOPNOTSUPP-style errors). The directory must already exist — a missing dir fails earlier at os.Open.
Common situations: Accidentally launching a duplicate systemd/docker instance after a config edit; running nsqd on NFS-mounted storage 'for shared persistence'; k8s hostPath/RWO volume attached twice; test scripts that forgot to kill the previous nsqd and reuse /tmp dirs.
Related errors
- failed to append certificate to pool
- unknown tlsVersionOption %q
- failed to read TLS root CA file %s - %s
- invalid E2E processing latency percentile: %v
- failed to read metadata from %s - %s
AI-assisted analysis of nsqio/nsq@85cf10c09c (2026-08-16).
Data as JSON: /api/errors/ea0f43d1e099b58f.
Report an issue: GitHub.