facebook/flow · error

mkdirp: mkdir failed

Error message

mkdirp: mkdir {} failed: {}

What it means

mkdirp creates a path one component at a time (unix branch, with explicit mode from _perm). AlreadyExists is tolerated, but any other error panics with the failing component. Real causes: EACCES/EROFS on a parent, ENOTDIR when a regular file occupies a component position, ENAMETOOLONG, or EDQUOT.

Solutions

  1. Remove or rename the file occupying the failing component path shown in the panic
  2. Fix write permissions on the parent directory (chmod/chown)
  3. Set TMPDIR to a clean, writable, local directory and retry
  4. Shorten deep paths or enable long-path support on Windows

Example fix

# before
# a stray FILE named 'flow' blocks <tmp>/flow/...
touch /tmp/flow && flow check   # panics: mkdirp: mkdir /tmp/flow/x failed: Not a directory

# after
rm /tmp/flow
flow check
Defensive patterns

Strategy: validation

Validate before calling

# verify every ancestor of flow's temp/cache path is a directory and writable
path="$TMPDIR/flow"; p=""
for part in $(echo "$path" | tr '/' ' '); do
  p="$p/$part"
  [ -e "$p" ] && [ ! -d "$p" ] && echo "BLOCKED: $p is a file"
done
test -w "$(dirname "$path")" || echo "parent not writable"

Prevention

When it happens

Trigger: Creating flow's cache/temp directory trees when an intermediate component is a regular file (path like <tmp>/file.json/sub); parent directory lacks write permission; read-only or quota-limited filesystem; extremely long paths.

Common situations: TMPDIR pointing at a full/locked-down location; a previous crash leaving a file where flow expects a directory tree; sandboxed environments denying mkdir; shared caches on network volumes.

Understand the failure class

Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.

Related errors


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

Appendix: source

Thrown at rust_port/crates/flow_common/src/files.rs:1376

        [first_part, rest @ ..]
            if format!("{}{}", first_part, std::path::MAIN_SEPARATOR) == path_prefix =>
        {
            rest
        }
        _ => &parts,
    };
    parts.iter().fold(path_prefix, |path_str, part| {
        let new_path_str = Path::new(&path_str)
            .join(part)
            .to_string_lossy()
            .into_owned();
        #[cfg(unix)]
        {
            use std::os::unix::fs::DirBuilderExt;
            match std::fs::DirBuilder::new().mode(_perm).create(&new_path_str) {
                Ok(()) => {}
                Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => {}
                Err(e) => panic!("mkdirp: mkdir {} failed: {}", new_path_str, e),
            }
        }
        #[cfg(not(unix))]
        {
            match std::fs::create_dir(&new_path_str) {
                Ok(()) => {}
                Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => {}
                Err(e) => panic!("mkdirp: mkdir {} failed: {}", new_path_str, e),
            }
        }
        new_path_str
    });
}

pub fn generate_is_within_node_modules_fn(
    root: &Path,
    options: &FileOptions,
) -> impl Fn(&str) -> bool {

View on GitHub (pinned to 21c11b2ead)