HTTP

Status Code

423 Locked

The resource is locked and cannot be accessed or modified. Learn about WebDAV locks and how to handle locked resources.

6 min read advanced Try in Playground

What is 423 Locked?

TL;DR: Resource is locked by another user or process and can’t be modified. Wait for lock to expire or contact the lock owner.

A 423 Locked status code means the resource you’re trying to access is currently locked and cannot be modified. Think of it like trying to edit a document that someone else has open with exclusive editing rights—you can view it, but you can’t make changes until they release the lock.

This status code is part of the WebDAV (Web Distributed Authoring and Versioning) extension and is used to prevent conflicting modifications in collaborative environments.

When Does This Happen?

You’ll see a 423 Locked response in these common situations:

1. Exclusive Write Lock

User A has exclusive lock on file
User B tries to modify → 423 Locked

2. WebDAV File Editing

Document checked out for editing
Another user tries to edit → 423 Locked

3. Administrative Lock

Resource locked by administrator
Regular user tries to modify → 423 Locked

4. Processing Lock

File being processed (e.g., virus scan, conversion)
User tries to access → 423 Locked (temporary)

5. Concurrent Edit Prevention

First user locks resource for editing
Second user attempts modification → 423 Locked

Example Responses

Basic WebDAV Lock:

HTTP/1.1 423 Locked
Content-Type: application/xml; charset=utf-8
Lock-Token: <urn:uuid:e71d4fae-5dec-22d6-fea5-00a0c91e6be4>

<?xml version="1.0" encoding="utf-8" ?>
<D:error xmlns:D="DAV:">
  <D:lock-token-submitted>
    <D:href>/documents/report.docx</D:href>
  </D:lock-token-submitted>
</D:error>
```text

**With Lock Information:**

```http
HTTP/1.1 423 Locked
Content-Type: application/json
Lock-Token: <urn:uuid:a1b2c3d4-e5f6-4789-a012-3456789abcde>
X-Lock-Owner: alice@example.com
X-Lock-Timeout: 900

{
  "error": "Resource Locked",
  "message": "This resource is currently locked and cannot be modified",
  "lock_details": {
    "lock_token": "urn:uuid:a1b2c3d4-e5f6-4789-a012-3456789abcde",
    "locked_by": "alice@example.com",
    "locked_at": "2026-01-18T14:30:00Z",
    "lock_timeout": 900,
    "lock_expires_at": "2026-01-18T14:45:00Z",
    "lock_type": "exclusive"
  },
  "action": "Wait for lock to expire or contact the lock owner"
}

Administrative Lock:

HTTP/1.1 423 Locked
Content-Type: application/json
X-Lock-Type: administrative
Retry-After: 3600

{
  "error": "Resource Locked",
  "message": "This resource is locked for administrative purposes",
  "lock_type": "administrative",
  "reason": "Security audit in progress",
  "locked_until": "2026-01-18T18:00:00Z",
  "contact": "admin@example.com"
}
```text

## Real-World Example

Imagine two team members trying to edit the same document simultaneously:

**User Alice Locks Document:**

```http
LOCK /documents/quarterly-report.docx HTTP/1.1
Host: webdav.example.com
Content-Type: text/xml
Depth: 0
Timeout: Second-900

<?xml version="1.0" encoding="utf-8" ?>
<D:lockinfo xmlns:D="DAV:">
  <D:lockscope><D:exclusive/></D:lockscope>
  <D:locktype><D:write/></D:locktype>
  <D:owner>alice@example.com</D:owner>
</D:lockinfo>

Response:
HTTP/1.1 200 OK
Lock-Token: <urn:uuid:abc-123-def-456>
Content-Type: application/xml

<?xml version="1.0" encoding="utf-8" ?>
<D:prop xmlns:D="DAV:">
  <D:lockdiscovery>
    <D:activelock>
      <D:locktoken><D:href>urn:uuid:abc-123-def-456</D:href></D:locktoken>
      <D:timeout>Second-900</D:timeout>
    </D:activelock>
  </D:lockdiscovery>
</D:prop>

User Bob Tries to Modify (Fails):

PUT /documents/quarterly-report.docx HTTP/1.1
Host: webdav.example.com
Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document
Content-Length: 45678

[Document content...]

Response:
HTTP/1.1 423 Locked
Content-Type: application/json
Lock-Token: <urn:uuid:abc-123-def-456>
X-Lock-Owner: alice@example.com

{
  "status": 423,
  "error": "Locked",
  "message": "Document is locked by another user",
  "details": {
    "resource": "/documents/quarterly-report.docx",
    "lock_token": "urn:uuid:abc-123-def-456",
    "locked_by": "alice@example.com",
    "locked_at": "2026-01-18T14:30:00Z",
    "lock_expires_at": "2026-01-18T14:45:00Z",
    "time_remaining": "14 minutes"
  },
  "actions": {
    "wait": "Wait for lock to expire in 14 minutes",
    "contact": "Contact alice@example.com to release lock",
    "force_unlock": "Admins can force unlock at /admin/locks/abc-123-def-456"
  }
}
```text

**User Bob with Valid Lock Token (Succeeds):**

```http
PUT /documents/quarterly-report.docx HTTP/1.1
Host: webdav.example.com
If: (<urn:uuid:abc-123-def-456>)  ← Valid lock token
Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document

[Document content...]

Response:
HTTP/1.1 204 No Content
Lock-Token: <urn:uuid:abc-123-def-456>

423 vs Other Access Control Codes

CodeMeaningCauseCan Retry?
423LockedResource locked (temporary)Yes, when unlocked
403ForbiddenNo permission (permanent)No, need authorization
401UnauthorizedNot authenticatedYes, with credentials
409ConflictState conflictYes, after resolving

Important Characteristics

Temporary vs Permanent:

423 Locked: Temporary restriction
- Resource is locked by another user/process
- Will become available when unlocked
- Usually has timeout

403 Forbidden: Permanent restriction
- User lacks permission
- Won't change without authorization change

Lock Types:

Exclusive Lock:
- Only lock holder can modify
- Others get 423 until lock released

Shared Lock:
- Multiple readers allowed
- Writers get 423
- Prevents writes, allows reads

WebDAV Lock Headers:

Lock-Token: <urn:uuid:lock-token-id>
Timeout: Second-3600
Depth: 0 or infinity
If: (<lock-token>)  ← Required to modify locked resource
```text

## Common Mistakes

**❌ Using 423 for permission issues**

```http
HTTP/1.1 423 Locked  ← Wrong! User lacks permission
Message: You don't have permission to access this resource

# Should be:
HTTP/1.1 403 Forbidden
Message: You don't have permission to access this resource

❌ Not providing lock information

HTTP/1.1 423 Locked
Content-Type: text/plain

Resource is locked.  ← Unhelpful, no details about lock
```text

**❌ Not implementing lock timeout**

```http
LOCK /resource → Lock created with no timeout
(User closes browser, lock never released)  ← Resource locked forever!

✅ Correct usage with full information

HTTP/1.1 423 Locked
Content-Type: application/json
Lock-Token: <urn:uuid:lock-id>
Retry-After: 900

{
  "error": "Locked",
  "lock_owner": "user@example.com",
  "lock_expires_at": "2026-01-18T15:00:00Z",
  "retry_after": 900
}
```text

## Best Practices

**Always Include Lock Details:**

```http
HTTP/1.1 423 Locked
Content-Type: application/json
Lock-Token: <urn:uuid:e71d4fae-5dec-22d6-fea5-00a0c91e6be4>
X-Lock-Owner: alice@example.com
Retry-After: 600

{
  "error": "Resource Locked",
  "message": "This resource is currently locked",
  "lock": {
    "token": "urn:uuid:e71d4fae-5dec-22d6-fea5-00a0c91e6be4",
    "owner": "alice@example.com",
    "type": "exclusive",
    "scope": "write",
    "created_at": "2026-01-18T14:30:00Z",
    "expires_at": "2026-01-18T14:40:00Z",
    "timeout_seconds": 600
  },
  "suggestions": [
    "Wait for lock to expire",
    "Contact lock owner to release",
    "Try again after lock expiration"
  ]
}

Implement Lock Timeouts:

// Express.js example
const locks = new Map()

app.lock('/documents/:id', (req, res) => {
  const docId = req.params.id
  const timeout = parseInt(req.headers.timeout?.replace('Second-', '')) || 900

  if (locks.has(docId)) {
    return res.status(423).json({
      error: 'Already locked',
      lock: locks.get(docId)
    })
  }

  const lockToken = `urn:uuid:${uuidv4()}`
  const expiresAt = Date.now() + timeout * 1000

  locks.set(docId, {
    token: lockToken,
    owner: req.user.email,
    expiresAt
  })

  // Auto-remove lock after timeout
  setTimeout(() => locks.delete(docId), timeout * 1000)

  res.status(200).set('Lock-Token', `<${lockToken}>`).json({ lockToken, expiresAt })
})

app.put('/documents/:id', (req, res) => {
  const docId = req.params.id
  const providedToken = req.headers.if?.match(/<(.+)>/)?.[1]

  const lock = locks.get(docId)

  if (lock) {
    if (lock.expiresAt < Date.now()) {
      locks.delete(docId) // Lock expired
    } else if (lock.token !== providedToken) {
      return res.status(423).json({
        error: 'Locked',
        lock_owner: lock.owner,
        lock_expires: new Date(lock.expiresAt)
      })
    }
  }

  // Proceed with update
  updateDocument(docId, req.body)
  res.status(204).send()
})
```javascript

**Provide Lock Management Interface:**

```javascript
// View active locks
app.get('/admin/locks', adminOnly, (req, res) => {
  const activeLocks = Array.from(locks.entries()).map(([id, lock]) => ({
    resource_id: id,
    ...lock,
    expires_in_seconds: Math.max(0, (lock.expiresAt - Date.now()) / 1000)
  }))

  res.json({ locks: activeLocks })
})

// Force unlock (admin only)
app.delete('/admin/locks/:token', adminOnly, (req, res) => {
  const token = req.params.token

  for (const [id, lock] of locks.entries()) {
    if (lock.token === token) {
      locks.delete(id)
      return res.json({ message: 'Lock removed', resource_id: id })
    }
  }

  res.status(404).json({ error: 'Lock not found' })
})

WebDAV Lock Implementation

Creating a Lock:

LOCK /documents/report.docx HTTP/1.1
Host: webdav.example.com
Content-Type: text/xml
Depth: 0
Timeout: Second-3600

<?xml version="1.0"?>
<D:lockinfo xmlns:D="DAV:">
  <D:lockscope><D:exclusive/></D:lockscope>
  <D:locktype><D:write/></D:locktype>
  <D:owner>alice@example.com</D:owner>
</D:lockinfo>
```http

**Refreshing a Lock:**

```http
LOCK /documents/report.docx HTTP/1.1
Host: webdav.example.com
If: (<urn:uuid:lock-token>)
Timeout: Second-1800

Unlocking:

UNLOCK /documents/report.docx HTTP/1.1
Host: webdav.example.com
Lock-Token: <urn:uuid:lock-token>
```javascript

## Implementation Examples

**Node.js/Express:**

```javascript
const locks = new Map()

function checkLock(req, res, next) {
  const resourceId = req.params.id
  const lock = locks.get(resourceId)

  if (!lock) return next()

  if (lock.expiresAt < Date.now()) {
    locks.delete(resourceId)
    return next()
  }

  const providedToken = req.headers.if?.match(/<(.+)>/)?.[1]

  if (lock.token !== providedToken) {
    return res.status(423).json({
      error: 'Locked',
      lock_token: lock.token,
      lock_owner: lock.owner,
      expires_at: new Date(lock.expiresAt).toISOString()
    })
  }

  next()
}

app.put('/files/:id', checkLock, (req, res) => {
  // Update file
  res.status(204).send()
})

Python/Django:

from django.http import JsonResponse
from django.utils import timezone
from datetime import timedelta
import uuid

locks = {}

def check_lock(view_func):
    def wrapper(request, resource_id, *args, **kwargs):
        lock = locks.get(resource_id)

        if lock and lock['expires_at'] > timezone.now():
            provided_token = request.META.get('HTTP_IF', '').strip('<>')

            if lock['token'] != provided_token:
                return JsonResponse({
                    'error': 'Locked',
                    'lock_owner': lock['owner'],
                    'expires_at': lock['expires_at'].isoformat()
                }, status=423)

        return view_func(request, resource_id, *args, **kwargs)

    return wrapper

@check_lock
def update_resource(request, resource_id):
    # Update resource
    return JsonResponse({'status': 'updated'})

Try It Yourself

Visit our request builder to simulate locked resources:

  1. Set method to LOCK
  2. Set path to /webdav/document.docx
  3. Click Send request to create lock
  4. Try PUT to same resource without lock token
  5. See 423 response with lock details

Frequently Asked Questions

What does 423 Locked mean?

A 423 error means the resource is currently locked and cannot be modified. This is primarily used in WebDAV for file locking during collaborative editing.

When is 423 Locked used?

It is used in WebDAV systems when a file is locked by another user, in version control systems during checkouts, or in collaborative editing to prevent conflicts.

How do I fix a 423 error?

Wait for the lock to be released, contact the user who holds the lock, or use the UNLOCK method in WebDAV to release the lock if you have permission.

What is the difference between 423 and 409?

423 means the resource is explicitly locked by a locking mechanism. 409 means there is a general conflict with resource state. 423 is for lock-based systems; 409 is for state conflicts.

Keep Learning