gradle/gradle · error · IllegalStateException

Unexpected lock protocol found in lock file. Expected %s, fo

Error message

Unexpected lock protocol found in lock file. Expected %s, found %s.

What it means

LockStateAccess parses the state region of a cache lock file, which is also version-prefixed; a mismatch between the on-disk protocol byte and the running Gradle's protocol raises this IllegalStateException. An empty or short region is not an error (EOFException yields the initial state), so it only fires when a complete record written by a different protocol version exists. Practically, another Gradle generation wrote this lock state.

Source

Thrown at platforms/core-execution/persistent-cache/src/main/java/org/gradle/cache/internal/filelock/LockStateAccess.java:84

        try {
            byte[] buffer = new byte[stateRegionSize];
            lockFileAccess.seek(REGION_START);

            int readPos = 0;
            while (readPos < buffer.length) {
                int nread = lockFileAccess.read(buffer, readPos, buffer.length - readPos);
                if (nread < 0) {
                    break;
                }
                readPos += nread;
            }

            ByteArrayInputStream inputStream = new ByteArrayInputStream(buffer, 0, readPos);
            DataInputStream dataInput = new DataInputStream(inputStream);

            byte protocolVersion = dataInput.readByte();
            if (protocolVersion != protocol.getVersion()) {
                throw new IllegalStateException(String.format("Unexpected lock protocol found in lock file. Expected %s, found %s.", protocol.getVersion(), protocolVersion));
            }
            return protocol.read(dataInput);
        } catch (EOFException e) {
            return protocol.createInitialState();
        }
    }

    public FileLockOutcome tryLock(RandomAccessFile lockFileAccess, boolean shared) throws IOException {
        try {
            FileLock fileLock = lockFileAccess.getChannel().tryLock(REGION_START, stateRegionSize, shared);
            if (fileLock == null) {
                return FileLockOutcome.LOCKED_BY_ANOTHER_PROCESS;
            } else {
                return FileLockOutcome.acquired(fileLock);
            }
        } catch (OverlappingFileLockException e) {
            return FileLockOutcome.LOCKED_BY_THIS_PROCESS;
        }

View on GitHub (pinned to 534f27719b)

Solutions

  1. Stop every running Gradle daemon across all installed versions, then retry
  2. Delete the lock files for the affected cache so fresh state is written
  3. Keep a single Gradle version per GRADLE_USER_HOME
  4. Standardize the Gradle wrapper version across teams and CI
Defensive patterns

Strategy: try-catch

Try / catch

try {
    lockStateAccess.readState(lockFileAccess);
} catch (IllegalStateException e) {
    if (String.valueOf(e.getMessage()).startsWith("Unexpected lock protocol")) {
        // stale lock state from another Gradle version: delete the lock file
    }
}

Prevention

When it happens

Trigger: Acquiring a cache lock whose state region was persisted by a Gradle build with a different lock state protocol, e.g. after a version switch with surviving daemons or shared caches.

Common situations: Switching Gradle versions while old daemons hold locks, mixed IDE/CLI versions on one machine, CI sharing a cache volume with developer workstations.

Related errors


AI-assisted analysis of gradle/gradle@534f27719b (2026-08-22). Data as JSON: /api/errors/bc15e911f402656d. Report an issue: GitHub.