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

Windows counterpart of error 213. In get_access_mode() (windows.rs:271-278), when read/write/append/access_mode are all unset but create/create_new/truncate IS set, the open is rejected with InvalidInput because creating or truncating requires write or append access.

Source

Thrown at library/std/src/sys/fs/windows.rs:275

    pub fn freeze_last_write_time(&mut self, freeze: bool) {
        self.freeze_last_write_time = freeze;
    }

    fn get_access_mode(&self) -> io::Result<u32> {
        match (self.read, self.write, self.append, self.access_mode) {
            (.., Some(mode)) => Ok(mode),
            (true, false, false, None) => Ok(c::GENERIC_READ),
            (false, true, false, None) => Ok(c::GENERIC_WRITE),
            (true, true, false, None) => Ok(c::GENERIC_READ | c::GENERIC_WRITE),
            (false, _, true, None) => Ok(c::FILE_GENERIC_WRITE & !c::FILE_WRITE_DATA),
            (true, _, true, None) => {
                Ok(c::GENERIC_READ | (c::FILE_GENERIC_WRITE & !c::FILE_WRITE_DATA))
            }
            (false, false, false, None) => {
                // 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_cmode_disposition(&self) -> io::Result<(u32, u32)> {
        match (self.write, self.append) {
            (true, false) => {}
            (false, false) => {
                if self.truncate || self.create || self.create_new {

View on GitHub (pinned to 7088e4b63a)

Solutions

  1. Add .write(true) or .append(true) to the builder.
  2. For exclusive create-if-absent, use .write(true).create_new(true).

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

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); // add .write(true)
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: `OpenOptions::new().create(true).open(p)` on Windows with no .read/.write/.append.

Common situations: Assuming .create(true) implies write; same builder mistake as on Unix but surfaced by the Windows backend.

Related errors


AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10). Data as JSON: /api/errors/0c730a9ab903f14e. Report an issue: GitHub.