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

  1. Move the lock file (and data dir) onto a local filesystem that supports flock instead of a network mount.
  2. Inspect the wrapped errno to identify the cause (EBADF, ENOLCK, etc.) and address it specifically.
  3. If running in a restricted sandbox/container, ensure the filesystem allows flock or run outside the sandbox.
  4. 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

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


AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29). Data as JSON: /api/errors/ba6cf1e746e94988. Report an issue: GitHub.