pytest-dev/pytest · error · OSError

cannot create lockfile in {p}

Error message

cannot create lockfile in {p}

What it means

create_cleanup_lock opens an exclusive (O_CREAT|O_EXCL) lock file to serialize cache-dir cleanup. If the file already exists it raises OSError('cannot create lockfile in {p}'), wrapping the underlying FileExistsError. A stale lock blocks cleanup.

Source

Thrown at src/_pytest/pathlib.py:295

        except Exception:
            pass
        else:
            _force_symlink(root, prefix + "current", new_path)
            return new_path
    else:
        raise OSError(
            "could not create numbered dir with prefix "
            f"{prefix} in {root} after 10 tries"
        )


def create_cleanup_lock(p: Path) -> Path:
    """Create a lock to prevent premature directory cleanup."""
    lock_path = get_lock_path(p)
    try:
        fd = os.open(str(lock_path), os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o644)
    except FileExistsError as e:
        raise OSError(f"cannot create lockfile in {p}") from e
    else:
        pid = os.getpid()
        spid = str(pid).encode()
        os.write(fd, spid)
        os.close(fd)
        if not lock_path.is_file():
            raise OSError("lock path got renamed after successful creation")
        return lock_path


def register_cleanup_lock_removal(lock_path: Path, register: Any) -> Any:
    """Register a cleanup function for removing a lock."""
    pid = os.getpid()

    def cleanup_on_exit(lock_path: Path = lock_path, original_pid: int = pid) -> None:
        current_pid = os.getpid()
        if current_pid != original_pid:
            # fork

View on GitHub (pinned to 98b357f69e)

Solutions

  1. Remove the stale .lock file in the cache directory (the path is echoed in the message)
  2. Ensure pytest processes sharing a cache dir are not run concurrently
  3. Use -p no:cacheprovider or a per-process --cachedir if concurrency is unavoidable

Example fix

// before
# stale .pytest_cache/.../lock present
// after
rm -f .pytest_cache/v/cache/*.lock  # then re-run pytest
Defensive patterns

Strategy: validation

Validate before calling

def ensure_no_stale_lock(cache_dir):
    from pathlib import Path
    for lock in Path(cache_dir).rglob('*.lock'):
        try:
            lock.unlink()
        except OSError:
            pass

Try / catch

try:
    create_cleanup_lock(p)
except OSError:
    # stale lock from a crashed run; remove and retry once
    get_lock_path(p).unlink(missing_ok=True)
    create_cleanup_lock(p)

Prevention

When it happens

Trigger: A leftover .lock file in the cache/temp dir from a previous pytest process that crashed or was killed before cleanup; or two pytest processes racing over the same cache dir.

Common situations: Previous run killed (SIGKILL, OOM, CI cancel) leaving a stale lock; multiple workers writing to the same cache; container restarts leaving locks behind.

Related errors


AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04). Data as JSON: /data/errors/a37174143e33f5fe.json. Report an issue: GitHub.