gastownhall/beads · warning

clearing lock metadata: %w

Error message

clearing lock metadata: %w

What it means

SyncLock.Release first clears or invalidates the advisory metadata (owner info) while still holding the kernel lock, then unlocks and closes the file. If clearSyncLockInfo fails, the error is captured and returned (after unlock/close succeed) wrapped as this message. The authoritative lock IS still released; only the diagnostics cleanup failed.

Source

Thrown at internal/linear/synclock.go:90

}

// Release releases the sync lock. The kernel-lock file is NOT removed — doing
// so after unlocking creates a race where a blocked waiter acquires the old
// inode while a new process creates a fresh file at the same path, splitting
// lock identity. On Unix, inline owner metadata is truncated while still
// holding the lock. On Windows, a separate advisory record is cleared while
// still holding the authoritative guard.
func (l *SyncLock) Release() error {
	if l == nil || l.file == nil {
		return nil
	}

	// Clear or invalidate diagnostic metadata before releasing the authoritative
	// lock. Platform helpers preserve Unix errors and make Windows diagnostics
	// best-effort.
	var metadataErr error
	if err := clearSyncLockInfo(l.file, l.infoPath, &l.metadata); err != nil {
		metadataErr = fmt.Errorf("clearing lock metadata: %w", err)
	}

	unlockErr := lockfile.FlockUnlock(l.file)
	closeErr := l.file.Close()
	l.file = nil

	if unlockErr != nil {
		return unlockErr
	}
	if closeErr != nil {
		return closeErr
	}
	return metadataErr
}

// SyncLockHeldError is returned when the lock is held by another process.
type SyncLockHeldError struct {
	Info *SyncLockInfo

View on GitHub (pinned to 71377f2769)

Solutions

  1. Treat as mostly benign: verify the kernel lock was released (unlock/close errors are returned first) before panicking
  2. Free disk space or fix filesystem permissions if the wrapped error is I/O or permission related
  3. Stop cleanup scripts from deleting files in the beads directory while syncs run
  4. Manually remove stale .linear-sync.lock metadata when no sync is running

Example fix

// before: failing hard on metadata cleanup
if err := lock.Release(); err != nil { return err }
// after: only fail on real unlock problems; log metadata issues
if err := lock.Release(); err != nil {
    if strings.Contains(err.Error(), "clearing lock metadata") {
        log.Warnf("lock metadata cleanup failed: %v", err)
        return nil
    }
    return err
}
Defensive patterns

Strategy: try-catch

Try / catch

if err := lock.Release(); err != nil {
    if strings.Contains(err.Error(), "clearing lock metadata") {
        log.Warnf("non-fatal: lock metadata cleanup failed: %v", err)
        return nil // kernel lock was still released
    }
    return err // real unlock/close failure
}

Prevention

When it happens

Trigger: Calling Release when clearSyncLockInfo cannot truncate the inline owner metadata (Unix) or clear the advisory record (Windows) — e.g. I/O error on the lock file, read-only remount mid-session, or Windows file-handle contention.

Common situations: Disk full at release time; filesystem remounted read-only; lock file deleted underneath the holder by a cleanup script; antivirus briefly locking the metadata file on Windows.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/68aaba5862458d54. Report an issue: GitHub.