# What changed in filelock

> 30 changes in filelock 4 from its official release notes, upgrade guides and advisories: 3 breaking, 3 security. Each one cited. Sources checked 2026-10-18. HTML: https://unstale.sh/pypi/filelock/

To see which of these apply to a repository, run `npx @unstale/cli init` in it.

## filelock 4

### Breaking changes

- On Windows, a mode without group and other bits creates the lock file with an owner-only permission list. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)
- Records are reached through descriptors opened without following symlinks, Windows junctions are refused, and heartbeats verify ownership before rewriting records. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)
- The lock directory and claims directory are created with the lock's mode and the sticky bit; a later acquisition narrows a wider directory it owns. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)

### Security

- On Windows, a mode without group and other bits now creates the database with an owner-only permission list. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)
- SQLite database access avoids journal, WAL, or shared-memory files placed beside the database by another account; unsafe directories use a private hard link, and unavailable hard links raise `OSError` on Windows. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)
- Claims are reached through descriptors opened without following symlinks, Windows junctions are refused, and a coordination directory owned by another account under a sticky parent is refused. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)

### Performance

- Importing filelock is about twice as fast because lock types other than FileLock load on first use. (4.2.0) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.0)

### Behavior and default changes

- On Linux and macOS, stale markers change hands in one atomic exchange; on other platforms without one, except Windows, the marker stays in place and waits for `timeout` or `break_lock()`. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)

### Fixes and other changes

- A failed acquire on a relative path whose working directory no longer exists now leaves the lock's hold count unchanged, so a later with lock block can release the lock correctly. The failed call still raises FileNotFoundError. (4.2.2) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.2)
- Signal-handler exceptions while joining the queue no longer block later calls, and release returns after many acquires give up behind a waiter. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)
- A `thread_local=True` lock shared by threads with their own event loops no longer deadlocks when one thread waits while another holds it. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)
- Canceling an acquire waiting for another process now stops the wait and raises cancellation instead of waiting for release or raising `Timeout`. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)
- Async read-write locks associate holds with their task owner, forget holds after a backend release that already let go, and free acquire memory on timeout or cancellation. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)
- Async read-write wrappers stop admitting readers into a level whose release was interrupted. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)
- Release gives back one level so synchronous readers of a shared singleton keep their own holds. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)
- A lookup no longer returns a cached lock whose relative path now resolves to another file, or a lock whose finalizer is running. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)
- A release interrupted by a signal handler no longer leaves the lock dropped, and the lock is reacquired after an interrupted release. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)
- A database schema taking more than a few kilobytes to load raises `ValueError` rather than running past the acquire timeout. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)
- On Windows, acquisition waits for its timeout and raises `Timeout`; a fork from another thread no longer waits for an acquire on a busy database. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)
- The path resolved when acquisition starts remains in use until the hold ends, avoiding locks or markers being redirected when the process changes directory. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)
- Closing a wrapper ends only holds acquired through that wrapper; wrappers refuse readers joining an ended hold, and closing one wrapper no longer ends another wrapper's nested hold. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)
- Lease markers are no longer removed or displaced while live because of marker replacement, reused inode numbers, time-namespace differences, or stale-break races. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)
- Soft lock markers are no longer removed or displaced while live because of empty marker contents, reused inode numbers, time-namespace differences, unreadable boot IDs, or marker replacement races. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)
- An empty marker is treated as held, preventing contenders from evicting markers belonging to older versions or owners still writing their record. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)
- Read levels are tracked per thread, so release by a thread holding none raises `RuntimeError`; after its heartbeat records a lost hold, it refuses new acquires until that hold is released. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)
- A commit a whole retention window behind the log is refused, preventing adjacent stalled generations from admitting a second writer; stale checks sample the clock before reading a holder record. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)
- Each concrete subclass now keeps its own singleton cache and construction guard, including after fork. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)
- A non-regular node at a sentinel private-record name raises `SoftFileLockProtocolError`. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)
- Opening the lock file no longer truncates a file the lock did not create or applies `mode` to it; an `on_acquired` hook writing holder metadata now truncates the file itself. (4.2.1) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.1)
- Fixes StrictSoftFileLock raising SoftFileLockProtocolError on Windows when a contender reads a claim while its owner is finishing the unlink. (4.2.0) — [release notes](https://github.com/tox-dev/filelock/releases/tag/4.2.0)
