{"record":{"id":"582fc469d15cd7ab","repo":"facebook/flow","slug":"fd-of-path-mkdir-no-fail","errorCode":null,"errorMessage":"fd_of_path: mkdir_no_fail({:?}): {}","messagePattern":"fd_of_path: mkdir_no_fail\\((.+?)\\): (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"rust_port/crates/flow_daemon/src/daemon.rs","lineNumber":350,"sourceCode":"{\n    entry::register(name, f)\n}\n\npub fn name_of_entry<P, I, O>(entry: &Entry<P, I, O>) -> &'static str {\n    entry::name_of_entry(entry)\n}\n\n// `Daemon.fd_of_path` in OCaml returns a `Unix.file_descr`. We return a\n// `std::fs::File` instead: it is the cross-platform Rust analogue (works on\n// both Unix and Windows), is convertible to `Stdio` via `Stdio::from(File)`\n// on every platform, and avoids the Unix-only `OwnedFd`.\npub fn fd_of_path(path: &Path) -> File {\n    sys_utils::with_umask(0o111, || {\n        if let Some(parent) = path.parent()\n            && !parent.as_os_str().is_empty()\n        {\n            sys_utils::mkdir_no_fail(parent)\n                .unwrap_or_else(|e| panic!(\"fd_of_path: mkdir_no_fail({:?}): {}\", parent, e));\n        }\n        std::fs::OpenOptions::new()\n            .read(true)\n            .write(true)\n            .create(true)\n            .truncate(true)\n            .open(path)\n            .unwrap_or_else(|e| panic!(\"fd_of_path: open({:?}): {}\", path, e))\n    })\n}\n\npub fn null_fd() -> File {\n    fd_of_path(Path::new(sys_utils::null_path()))\n}\n\n// `StdioFd` lets callers either inherit one of the parent's standard streams\n// (matching OCaml's `if stdin <> Unix.stdin then close_if_open stdin` at lines\n// 207-213, where passing `Unix.stdin` means \"inherit\") or pass an owned file","sourceCodeStart":332,"sourceCodeEnd":368,"githubUrl":"https://github.com/facebook/flow/blob/f88ac94bcf6992f5d5a158854d94613ebb92c6e6/rust_port/crates/flow_daemon/src/daemon.rs#L332-L368","documentation":"fd_of_path prepares daemon redirect targets: with umask 0o111 it first creates the path's parent directories via mkdir_no_fail, which tolerates AlreadyExists and forwards other errors; this panic reports that mkdir failure. Causes: EACCES/EROFS on the temp root, ENOTDIR when a file occupies a component, ENOSPC, or quota exhaustion.","triggerScenarios":"Creating the parent tree for a daemon stdio/log path under TMPDIR when TMPDIR is unwritable, read-only, full, or contains a file where a directory component is needed.","commonSituations":"Hardened CI containers with restrictive /tmp; TMPDIR pointed at a read-only volume; leftover regular files from earlier crashed runs blocking the directory tree; disk quota hit on shared hosts.","solutions":["Set TMPDIR to a clean, writable, local directory and retry","Remove files occupying the parent path reported in the panic","Fix permissions or remount read-write the volume holding the temp dir","Free space / raise quota if ENOSPC/EDQUOT"],"exampleFix":"# before\nTMPDIR=/readonly-vol/tmp flow start   # panics: fd_of_path: mkdir_no_fail(...)\n\n# after\nmkdir -p /local/tmp\nTMPDIR=/local/tmp flow start","handlingStrategy":"validation","validationCode":"# before starting the daemon\ntest -n \"$TMPDIR\" && test -d \"$TMPDIR\" && test -w \"$TMPDIR\" || echo \"TMPDIR invalid/unwritable\"\ndf -h \"${TMPDIR:-/tmp}\" | tail -1   # watch for a full volume","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set TMPDIR explicitly to a local writable directory in CI and containers","Periodically clean flow's temp tree of stale files/dirs from crashed runs","Keep temp volumes off read-only mounts and away from quota ceilings"],"tags":["daemon","filesystem","mkdir","tmpdir","permissions"],"backgroundTag":"mkdir-permission-denied","analyzedSha":"f88ac94bcf6992f5d5a158854d94613ebb92c6e6","analyzedAt":"2026-08-20T10:41:37.992Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}