{"record":{"id":"136d9a0e5f8cc59a","repo":"tokio-rs/tokio","slug":"not-in-o-wronly-or-o-rdwr-access-mode","errorCode":null,"errorMessage":"not in O_WRONLY or O_RDWR access mode","messagePattern":"not in O_WRONLY or O_RDWR access mode","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"tokio/src/net/unix/pipe.rs","lineNumber":429,"sourceCode":"    /// # Panics\n    ///\n    /// This function panics if it is not called from within a runtime with\n    /// IO enabled.\n    ///\n    /// The runtime is usually set implicitly when this function is called\n    /// from a future driven by a tokio runtime, otherwise runtime can be set\n    /// explicitly with [`Runtime::enter`](crate::runtime::Runtime::enter) function.\n    pub fn from_owned_fd(owned_fd: OwnedFd) -> io::Result<Sender> {\n        if !is_pipe(owned_fd.as_fd())? {\n            return Err(io::Error::new(io::ErrorKind::InvalidInput, \"not a pipe\"));\n        }\n\n        let flags = get_file_flags(owned_fd.as_fd())?;\n        if has_write_access(flags) {\n            set_nonblocking(owned_fd.as_fd(), flags)?;\n            Sender::from_owned_fd_unchecked(owned_fd)\n        } else {\n            Err(io::Error::new(\n                io::ErrorKind::InvalidInput,\n                \"not in O_WRONLY or O_RDWR access mode\",\n            ))\n        }\n    }\n\n    /// Creates a new `Sender` from a [`File`] without checking pipe properties.\n    ///\n    /// This function is intended to construct a pipe from a File representing\n    /// a special FIFO file. The conversion assumes nothing about the underlying\n    /// file; it is left up to the user to make sure it is opened with write access,\n    /// represents a pipe and is set in non-blocking mode.\n    ///\n    /// # Examples\n    ///\n    /// ```no_run\n    /// use tokio::net::unix::pipe;\n    /// use std::fs::OpenOptions;","sourceCodeStart":411,"sourceCodeEnd":447,"githubUrl":"https://github.com/tokio-rs/tokio/blob/625954f365727668cb02d04172b34f1149637728/tokio/src/net/unix/pipe.rs#L411-L447","documentation":"Sender::from_owned_fd's second guard: after confirming the fd is a pipe, it reads the file flags and checks has_write_access; if neither O_WRONLY nor O_RDWR is set, it errors InvalidInput 'not in O_WRONLY or O_RDWR access mode'. You cannot wrap a read-only pipe end as a Sender.","triggerScenarios":"Calling Sender::from_owned_fd with a pipe fd that was opened read-only (O_RDONLY) — typically the read end of a pipe pair, or a FIFO opened without write permission.","commonSituations":"Mixing up the read and write ends of pipe(); opening a FIFO with O_RDONLY and trying to send; permission bits on the FIFO that exclude write for the opener.","solutions":["Pass the write end of the pipe pair to Sender::from_owned_fd (and the read end to Receiver::from_owned_fd).","Open the FIFO with write access (and O_NONBLOCK) if you intend to send.","Check the fd's access mode (getfl) before calling and route to Receiver vs Sender accordingly.","Use os_pipe::pipe() / tokio's own pipe() helpers so the ends are typed correctly from the start."],"exampleFix":"// before\nlet (read, write) = os_pipe::pipe()?;\nlet s = Sender::from_owned_fd(read)?; // wrong end\n\n// after\nlet (read, write) = os_pipe::pipe()?;\nlet s = Sender::from_owned_fd(write)?;\nlet r = Receiver::from_owned_fd(read)?;","handlingStrategy":"validation","validationCode":"use nix::fcntl::FcntlFlag;\nuse nix::fcntl::fcntl;\nuse std::os::unix::io::AsRawFd;\nlet flags = FcntlFlag::from_bits_truncate(fcntl(fd.as_raw_fd(), Fcntl::F_GETFL)?);\nif !flags.intersects(FcntlFlag::O_WRONLY | FcntlFlag::O_RDWR) {\n    return Err(anyhow::anyhow!(\"fd not opened for writing\"));\n}\nSender::from_owned_fd(fd)?;","typeGuard":"fn is_not_writable(e: &io::Error) -> bool {\n    e.kind() == io::ErrorKind::InvalidInput && e.to_string().contains(\"O_WRONLY\")\n}","tryCatchPattern":"match Sender::from_owned_fd(fd) {\n    Ok(s) => Ok(s),\n    Err(e) if e.to_string().contains(\"access mode\") => {\n        Err(anyhow::anyhow!(\"fd is read-only; pass the write end of the pipe\"))\n    }\n    Err(e) => Err(e.into()),\n}","preventionTips":["Pass the write end of pipe() to Sender::from_owned_fd.","Open FIFOs intended for sending with write access and O_NONBLOCK.","Check the access mode with F_GETFL before calling.","Use typed helpers (os_pipe::pipe) so the ends aren't swapped."],"tags":["unix","pipe","fd","access-mode","sender","tokio"],"backgroundTag":null,"analyzedSha":"625954f365727668cb02d04172b34f1149637728","analyzedAt":"2026-08-11T17:46:45.378Z","contentChangedAt":"2026-08-11T17:46:45.378Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}