diff --git a/lib/private/Files/Storage/Common.php b/lib/private/Files/Storage/Common.php
index 001b16cb3b410ab0169ff2f2b35362ae3d725a26..6c57405619af0b0bf87a558015c89ea072e99d43 100644
--- a/lib/private/Files/Storage/Common.php
+++ b/lib/private/Files/Storage/Common.php
@@ -747,7 +747,7 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage {
 			);
 		}
 		try {
-			$provider->acquireLock('files/' . md5($this->getId() . '::' . trim($path, '/')), $type);
+			$provider->acquireLock('files/' . md5($this->getId() . '::' . trim($path, '/')), $type, $this->getId() . '::' . $path);
 		} catch (LockedException $e) {
 			if ($logger) {
 				$logger->logException($e, ['level' => ILogger::INFO]);
diff --git a/lib/private/Lock/DBLockingProvider.php b/lib/private/Lock/DBLockingProvider.php
index c32d7b4877a6c68516256a5244991f57ffbbaeda..f48bf57028f9b2145a7ba8f1e9d52a5e29241a6e 100644
--- a/lib/private/Lock/DBLockingProvider.php
+++ b/lib/private/Lock/DBLockingProvider.php
@@ -180,7 +180,7 @@ class DBLockingProvider extends AbstractLockingProvider {
 	 * @param int $type self::LOCK_SHARED or self::LOCK_EXCLUSIVE
 	 * @throws \OCP\Lock\LockedException
 	 */
-	public function acquireLock(string $path, int $type) {
+	public function acquireLock(string $path, int $type, string $readablePath = null) {
 		$expire = $this->getExpireTime();
 		if ($type === self::LOCK_SHARED) {
 			if (!$this->isLocallyLocked($path)) {
@@ -208,7 +208,7 @@ class DBLockingProvider extends AbstractLockingProvider {
 			}
 		}
 		if ($result !== 1) {
-			throw new LockedException($path);
+			throw new LockedException($path, null, null, $readablePath);
 		}
 		$this->markAcquire($path, $type);
 	}
diff --git a/lib/private/Lock/MemcacheLockingProvider.php b/lib/private/Lock/MemcacheLockingProvider.php
index 3d7510f43ffd015b36e2b90ecad835718e1cd9c5..c9dfcea3197aebb907ba49b30c0c298d0983b1d2 100644
--- a/lib/private/Lock/MemcacheLockingProvider.php
+++ b/lib/private/Lock/MemcacheLockingProvider.php
@@ -71,17 +71,18 @@ class MemcacheLockingProvider extends AbstractLockingProvider {
 	/**
 	 * @param string $path
 	 * @param int $type self::LOCK_SHARED or self::LOCK_EXCLUSIVE
+	 * @param string $readablePath human readable path to use in error messages
 	 * @throws \OCP\Lock\LockedException
 	 */
-	public function acquireLock(string $path, int $type) {
+	public function acquireLock(string $path, int $type, string $readablePath = null) {
 		if ($type === self::LOCK_SHARED) {
 			if (!$this->memcache->inc($path)) {
-				throw new LockedException($path, null, $this->getExistingLockForException($path));
+				throw new LockedException($path, null, $this->getExistingLockForException($path), $readablePath);
 			}
 		} else {
 			$this->memcache->add($path, 0);
 			if (!$this->memcache->cas($path, 0, 'exclusive')) {
-				throw new LockedException($path, null, $this->getExistingLockForException($path));
+				throw new LockedException($path, null, $this->getExistingLockForException($path), $readablePath);
 			}
 		}
 		$this->setTTL($path);
diff --git a/lib/private/Lock/NoopLockingProvider.php b/lib/private/Lock/NoopLockingProvider.php
index 94612e22f53382177743d28ff1211d92ed3de4ff..4f38d5159b91c2484d7422310b64e7a6f0f368af 100644
--- a/lib/private/Lock/NoopLockingProvider.php
+++ b/lib/private/Lock/NoopLockingProvider.php
@@ -46,7 +46,7 @@ class NoopLockingProvider implements ILockingProvider {
 	/**
 	 * {@inheritdoc}
 	 */
-	public function acquireLock(string $path, int $type) {
+	public function acquireLock(string $path, int $type, string $readablePath = null) {
 		// do nothing
 	}
 
diff --git a/lib/public/Lock/ILockingProvider.php b/lib/public/Lock/ILockingProvider.php
index 34f69abdc090d10af46a08d19ca1e84fbf0b1216..6886b176c40a134e1940c977568cd46ae9cdefd5 100644
--- a/lib/public/Lock/ILockingProvider.php
+++ b/lib/public/Lock/ILockingProvider.php
@@ -55,10 +55,11 @@ interface ILockingProvider {
 	/**
 	 * @param string $path
 	 * @param int $type self::LOCK_SHARED or self::LOCK_EXCLUSIVE
+	 * @param string $readablePath human readable path to use in error messages, since 20.0.0
 	 * @throws \OCP\Lock\LockedException
 	 * @since 8.1.0
 	 */
-	public function acquireLock(string $path, int $type);
+	public function acquireLock(string $path, int $type, string $readablePath = null);
 
 	/**
 	 * @param string $path
diff --git a/lib/public/Lock/LockedException.php b/lib/public/Lock/LockedException.php
index 582157010ccb5d3d8814b2e1ea0abb373f7776ca..4bd59c81b349d36d0b5ae427a6183bc3bc36a004 100644
--- a/lib/public/Lock/LockedException.php
+++ b/lib/public/Lock/LockedException.php
@@ -53,10 +53,15 @@ class LockedException extends \Exception {
 	 * @param string $path locked path
 	 * @param \Exception|null $previous previous exception for cascading
 	 * @param string $existingLock since 14.0.0
+	 * @param string $readablePath since 20.0.0
 	 * @since 8.1.0
 	 */
-	public function __construct(string $path, \Exception $previous = null, string $existingLock = null) {
-		$message = '"' . $path . '" is locked';
+	public function __construct(string $path, \Exception $previous = null, string $existingLock = null, string $readablePath = null) {
+		if ($readablePath) {
+			$message = "\"$path\"(\"$readablePath\") is locked";
+		} else {
+			$message = '"' . $path . '" is locked';
+		}
 		$this->existingLock = $existingLock;
 		if ($existingLock) {
 			$message .= ', existing lock on file: ' . $existingLock;