rust-lang/rust · error · io::Error
creating or truncating a file requires write or append acces
Error message
creating or truncating a file requires write or append access
What it means
When computing Unix open flags in get_access_mode(), the case (read, write, append) = (false, false, false) is invalid. If a creation/truncation flag (create, create_new, truncate) IS set, this more specific error is returned because creating or truncating requires write or append access (unix.rs:1161-1169).
Source
Thrown at library/std/src/sys/fs/unix.rs:1165
self.custom_flags = flags;
}
#[cfg(not(target_os = "wasi"))]
pub fn mode(&mut self, mode: u32) {
self.mode = mode as mode_t;
}
fn get_access_mode(&self) -> io::Result<c_int> {
match (self.read, self.write, self.append) {
(true, false, false) => Ok(libc::O_RDONLY),
(false, true, false) => Ok(libc::O_WRONLY),
(true, true, false) => Ok(libc::O_RDWR),
(false, _, true) => Ok(libc::O_WRONLY | libc::O_APPEND),
(true, _, true) => Ok(libc::O_RDWR | libc::O_APPEND),
(false, false, false) => {
// If no access mode is set, check if any creation flags are set
// to provide a more descriptive error message
if self.create || self.create_new || self.truncate {
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"creating or truncating a file requires write or append access",
))
} else {
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"must specify at least one of read, write, or append access",
))
}
}
}
}
fn get_creation_mode(&self) -> io::Result<c_int> {
match (self.write, self.append) {
(true, false) => {}
(false, false) => {
if self.truncate || self.create || self.create_new {View on GitHub (pinned to 7088e4b63a)
Solutions
- Add .write(true) (or .append(true)) to the OpenOptions builder.
- For exclusive create-if-absent, use .write(true).create_new(true).
- Drop the creation flag if you only intend to read.
Example fix
// before
std::fs::OpenOptions::new().create(true).open("f")?;
// after
std::fs::OpenOptions::new().write(true).create(true).open("f")? Defensive patterns
Strategy: validation
Validate before calling
fn can_open(opts: &std::fs::OpenOptions) -> bool {
// create/create_new/truncate require write or append
let needs_write = true; // mirror std check via the public API is not possible;
// instead, validate your builder explicitly before open:
// ensure write or append is set whenever create/truncate is used.
needs_write && true
} Try / catch
match std::fs::OpenOptions::new().create(true).open(p) {
Ok(f) => f,
Err(e) if e.kind() == std::io::ErrorKind::InvalidInput => {
return Err(e); // fix the builder: add .write(true)
}
Err(e) => return Err(e),
} Prevention
- Whenever you set .create/.create_new/.truncate, also set .write(true) or .append(true).
- Wrap OpenOptions construction in a helper that enforces the access+creation invariant.
When it happens
Trigger: `OpenOptions::new().create(true).open(p)` or `.create_new(true).open(p)` or `.truncate(true).open(p)` with no .read/.write/.append set.
Common situations: Assuming .create(true) implies write access; copying an OpenOptions chain and dropping the access setter; building a 'touch'-style open incorrectly.
Related errors
- must specify at least one of read, write, or append access
- creating or truncating a file requires write or append acces
- must specify at least one of read, write, or append access
- Path already exists
- process groups are not supported on espidf
AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10).
Data as JSON: /api/errors/6655b9a27756b087.
Report an issue: GitHub.