pola-rs/polars · critical

failed to open/create global file cache lockfile

Error message

failed to open/create global file cache lockfile: {err}

What it means

The global file cache lockfile cannot be opened or created at the lock path, and the library panics instead of proceeding without the lock. The lockfile coordinates the background eviction manager. Failure almost always indicates filesystem permission or path issues.

Solutions

  1. Verify the cache directory and its parent are writable by the current user
  2. Point POLARS_TEMP_DIR to a writable location
  3. Check for sandbox/seccomp/SELinux rules blocking file creation in the temp dir
  4. Ensure a stale root-owned lockfile isn't blocking creation (fix ownership or remove it)

Example fix

// before
POLARS_TEMP_DIR=/var/lock (root-owned)
// after
POLARS_TEMP_DIR=/home/user/.cache/polars
Defensive patterns

Strategy: validation

Validate before calling

use std::fs;
let base = std::env::var("POLARS_TEMP_DIR").unwrap_or_else(|_| std::env::temp_dir().display().to_string());
let lock_probe = format!("{base}/.polars-lock-probe");
match fs::OpenOptions::new().write(true).create(true).truncate(false).open(&lock_probe) {
    Ok(_) => { let _ = fs::remove_file(&lock_probe); }
    Err(e) => panic!("cannot create lockfiles in {base}: {e}"),
}

Prevention

When it happens

Trigger: First initialization of the file cache lock: OpenOptions write+create on the lockfile path fails (EACCES, EROFS, ENOENT parent, etc.).

Common situations: Read-only temp directories, restrictive sandbox/SELinux policies, or a directory path owned by another user in multi-user environments.

Understand the failure class

Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.

Related errors


AI-assisted analysis of pola-rs/polars@fe841f959e (2026-09-18). Data as JSON: /api/errors/d62bb3ee83462cf5. Report an issue: GitHub.

Appendix: source

Thrown at crates/polars-io/src/file_cache/cache_lock.rs:20

use std::sync::{Arc, LazyLock};
use std::time::Duration;

use fs4::FileExt;
use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
use polars_core::runtime::ASYNC;

use super::utils::FILE_CACHE_PREFIX;

pub(super) static GLOBAL_FILE_CACHE_LOCK: LazyLock<GlobalLock> = LazyLock::new(|| {
    let path = FILE_CACHE_PREFIX.join(".process-lock");

    let file = std::fs::OpenOptions::new()
        .write(true)
        .create(true)
        .truncate(false)
        .open(path)
        .map_err(|err| {
            panic!("failed to open/create global file cache lockfile: {err}");
        })
        .unwrap();

    let at_bool = Arc::new(AtomicBool::new(false));
    // Holding this access tracker prevents the background task from
    // unlocking the lock.
    let access_tracker = AccessTracker(at_bool.clone());
    let notify_lock_acquired = Arc::new(tokio::sync::Notify::new());
    let notify_lock_acquired_2 = notify_lock_acquired.clone();

    ASYNC.spawn(async move {
        let at_bool = std::mem::ManuallyDrop::new(at_bool);
        let access_tracker = at_bool.as_ref();
        let notify_lock_acquired = notify_lock_acquired_2;
        let verbose = false;

        loop {
            if verbose {

View on GitHub (pinned to fe841f959e)