facebook/flow · error

failed to write flowlib file

Error message

failed to write flowlib file

What it means

Panics when fs::write fails while extract() materializes the embedded flowlib/prelude/tslib files into the lib dir. mkdir created the directories just before, so failure means permissions, a read-only filesystem, concurrent removal of the dir, or a full disk at write time.

Source

Thrown at rust_port/crates/flow_flowlib/src/lib.rs:104

pub fn path_of_libdir(libdir: &LibDir) -> &Path {
    match libdir {
        LibDir::Prelude(path) => path,
        LibDir::Flowlib(path) => path,
        LibDir::Tslib(path) => path,
    }
}

fn mkdir(libdir: &LibDir) {
    let path = path_of_libdir(libdir);
    let parent_dir = path.parent().expect("libdir path should have a parent");
    sys_utils::mkdir_no_fail(parent_dir)
        .unwrap_or_else(|e| panic!("mkdir_no_fail({:?}): {}", parent_dir, e));
    sys_utils::mkdir_no_fail(path).unwrap_or_else(|e| panic!("mkdir_no_fail({:?}): {}", path, e));
}

fn write_flowlib(dir: &Path, (filename, contents): &(&str, &str)) {
    let file = dir.join(filename);
    fs::write(&file, contents).expect("failed to write flowlib file");
}

pub fn extract(libdir: &LibDir) {
    mkdir(libdir);
    let (path, lib) = match libdir {
        LibDir::Prelude(path) => (path.as_path(), BuiltinLib::Prelude),
        LibDir::Flowlib(path) => (path.as_path(), BuiltinLib::Flowlib),
        LibDir::Tslib(path) => (path.as_path(), BuiltinLib::Tslib),
    };
    for entry in contents(lib) {
        write_flowlib(path, entry);
    }
}

pub fn extract_if_missing(libdir: &LibDir) {
    let sentinel_name = match libdir {
        LibDir::Flowlib(_) => "core.js",
        LibDir::Prelude(_) => "prelude.js",

View on GitHub (pinned to f88ac94bcf)

Solutions

  1. Remove the stale lib dir (the whole flowlib temp path) and let extract recreate it with current user ownership
  2. Check ownership/permissions on the lib dir path and its parent; chmod/chown as needed
  3. Point the lib dir at a writable location (temp dir override / TMPDIR) when on a read-only filesystem
  4. Ensure only one process extracts into a given lib dir at a time (extract_if_missing guards this)

Example fix

// before
fn write_flowlib(dir: &Path, (filename, contents): &(&str, &str)) {
    let file = dir.join(filename);
    fs::write(&file, contents).expect("failed to write flowlib file");
}

// after — one clean retry after wiping a stale/locked dir
fn write_flowlib(dir: &Path, (filename, contents): &(&str, &str)) {
    let file = dir.join(filename);
    if let Err(e) = fs::write(&file, contents) {
        let _ = fs::remove_dir_all(dir);
        sys_utils::mkdir_no_fail(dir).unwrap_or_else(|e| panic!("mkdir_no_fail({dir:?}): {e}"));
        fs::write(&file, contents).unwrap_or_else(|e| panic!("failed to write flowlib file after retry: {e}"));
    }
}
Defensive patterns

Strategy: retry

Validate before calling

// Pre-check that the lib dir is writable before extract()
fn dir_writable(dir: &Path) -> bool {
    let probe = dir.join(".write_probe");
    let ok = std::fs::write(&probe, b"").is_ok();
    let _ = std::fs::remove_file(&probe);
    ok
}

if !dir_writable(libdir_path) {
    return Err(anyhow::anyhow!("libdir {:?} not writable", libdir_path));
}

Prevention

When it happens

Trigger: Running extract (or extract_if_missing) when the lib dir or its parent is owned by another user (e.g. created by a previous sudo run); the dir is on a read-only container layer; two flow processes extract into the same dir and one wipes it mid-write; disk full.

Common situations: Stale flowlib directory owned by root after running flow with sudo; Docker/Kubernetes read-only root filesystems without a writable overlay for the lib dir; Windows antivirus briefly locking freshly written files; shared CI caches with mixed UIDs.

Related errors


AI-assisted analysis of facebook/flow@f88ac94bcf (2026-08-20). Data as JSON: /api/errors/0b40f8de4aa96c50. Report an issue: GitHub.