charmbracelet/crush · error
flock: %w
Error message
flock: %w
What it means
lockFile retries unix.Flock with LOCK_EX|LOCK_NB in a loop. If Flock fails with an error other than EWOULDBLOCK (i.e., not simple contention), the retry loop aborts and this error wraps the raw errno. Typical errnos: EBADF (bad fd), EINTR handling, EOL3/NOLCK (system lock table full), or EDEADLK.
Source
Thrown at internal/lock/lock_unix.go:27
"os"
"time"
"golang.org/x/sys/unix"
)
// retrySleep is the interval between non-blocking flock retries in the
// blocking File path. Small enough that contention resolution feels
// snappy; large enough that we don't burn a CPU spinning.
const retrySleep = 100 * time.Millisecond
func lockFile(ctx context.Context, f *os.File) (func(), error) {
for {
err := unix.Flock(int(f.Fd()), unix.LOCK_EX|unix.LOCK_NB)
if err == nil {
return func() { _ = unix.Flock(int(f.Fd()), unix.LOCK_UN) }, nil
}
if !errors.Is(err, unix.EWOULDBLOCK) {
return nil, fmt.Errorf("flock: %w", err)
}
select {
case <-ctx.Done():
return nil, fmt.Errorf("acquire lock: %w", ctx.Err())
case <-time.After(retrySleep):
}
}
}
func tryLockFile(f *os.File) (func(), error) {
if err := unix.Flock(int(f.Fd()), unix.LOCK_EX|unix.LOCK_NB); err != nil {
if errors.Is(err, unix.EWOULDBLOCK) {
return nil, ErrContended
}
return nil, fmt.Errorf("flock: %w", err)
}
return func() { _ = unix.Flock(int(f.Fd()), unix.LOCK_UN) }, nil
}View on GitHub (pinned to 7944b8e522)
Solutions
- Move the lock file (and data dir) onto a local filesystem that supports flock instead of a network mount.
- Inspect the wrapped errno to identify the cause (EBADF, ENOLCK, etc.) and address it specifically.
- If running in a restricted sandbox/container, ensure the filesystem allows flock or run outside the sandbox.
- Reduce the number of simultaneous file locks if the system lock table is exhausted.
Defensive patterns
Strategy: fallback
Validate before calling
// avoid unsupported filesystems for lock files
if isNetworkMount(filepath.Dir(path)) {
return fmt.Errorf("lock file must be on a local filesystem supporting flock")
} Try / catch
release, err := lock.File(ctx, path)
if err != nil && !errors.Is(err, lock.ErrContended) {
return fmt.Errorf("flock unavailable on this filesystem: %w", err)
} Prevention
- Keep lock files on local disks, not NFS/SMB mounts.
- Check the wrapped errno to diagnose EBADF vs ENOLCK quickly.
- Verify sandbox/container policies permit flock before deployment.
When it happens
Trigger: Calling lock.File on a platform where unix.Flock fails with a non-contention error, e.g. the file descriptor became invalid, the filesystem does not support flock (some network mounts like certain NFS configs), or the kernel lock table is exhausted.
Common situations: Lock file on an NFS/network mount that doesn't support flock; running in a container/sandbox that blocks flock; heavy lock usage exhausting the system-wide lock table.
Related errors
- acquire config lock: %w
- open lock file %q: %w
- LockFileEx: %w
- failed to create parent directories: %w
- failed to create output file: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/ba6cf1e746e94988.
Report an issue: GitHub.