From 189a29db20de25321311cd90a182f58732344740 Mon Sep 17 00:00:00 2001 From: THARUN Date: Sat, 8 Aug 2026 01:28:12 +0530 Subject: [PATCH] Improve OpenOptions append+truncate error message --- library/std/src/fs/tests.rs | 22 +++++++++++++++++----- library/std/src/sys/fs/unix.rs | 2 +- library/std/src/sys/fs/windows.rs | 2 +- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 1b069f2e77f6b..a8b520b1fb372 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1506,6 +1506,7 @@ fn open_flavors() { // This error string is set by std itself so we are not at the whim of the OS here. let invalid_options = "creating or truncating a file requires write or append access"; + let append_truncate_error = "append and truncate cannot both be enabled"; // Test various combinations of creation modes and access modes. // @@ -1543,15 +1544,21 @@ fn open_flavors() { // append check!(c(&a).create_new(true).open(&tmpdir.join("d"))); - error_contains!(c(&a).create(true).truncate(true).open(&tmpdir.join("d")), invalid_options); - error_contains!(c(&a).truncate(true).open(&tmpdir.join("d")), invalid_options); + error_contains!( + c(&a).create(true).truncate(true).open(&tmpdir.join("d")), + append_truncate_error + ); + error_contains!(c(&a).truncate(true).open(&tmpdir.join("d")), append_truncate_error); check!(c(&a).create(true).open(&tmpdir.join("d"))); check!(c(&a).open(&tmpdir.join("d"))); // read-append check!(c(&ra).create_new(true).open(&tmpdir.join("e"))); - error_contains!(c(&ra).create(true).truncate(true).open(&tmpdir.join("e")), invalid_options); - error_contains!(c(&ra).truncate(true).open(&tmpdir.join("e")), invalid_options); + error_contains!( + c(&ra).create(true).truncate(true).open(&tmpdir.join("e")), + append_truncate_error + ); + error_contains!(c(&ra).truncate(true).open(&tmpdir.join("e")), append_truncate_error); check!(c(&ra).create(true).open(&tmpdir.join("e"))); check!(c(&ra).open(&tmpdir.join("e"))); @@ -2362,7 +2369,6 @@ fn test_open_options_invalid_combinations() { (|| OO::new().create(true).read(true).clone(), "create without write"), (|| OO::new().create_new(true).read(true).clone(), "create_new without write"), (|| OO::new().truncate(true).read(true).clone(), "truncate without write"), - (|| OO::new().truncate(true).append(true).clone(), "truncate with append"), ]; for (make_opts, desc) in test_cases { @@ -2377,7 +2383,13 @@ fn test_open_options_invalid_combinations() { "{desc} - wrong error message" ); } + let result = OO::new().truncate(true).append(true).open("nonexistent.txt"); + assert!(result.is_err(), "truncate with append should fail"); + + let err = result.unwrap_err(); + assert_eq!(err.kind(), ErrorKind::InvalidInput); + assert_eq!(err.to_string(), "append and truncate cannot both be enabled"); let result = OO::new().open("nonexistent.txt"); assert!(result.is_err(), "no access mode should fail"); let err = result.unwrap_err(); diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 3caa41e16845d..c6ae7faf5f995 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -1186,7 +1186,7 @@ impl OpenOptions { if self.truncate && !self.create_new { return Err(io::Error::new( io::ErrorKind::InvalidInput, - "creating or truncating a file requires write or append access", + "append and truncate cannot both be enabled", )); } } diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs index a94a6f61cf118..e0e282a181e79 100644 --- a/library/std/src/sys/fs/windows.rs +++ b/library/std/src/sys/fs/windows.rs @@ -301,7 +301,7 @@ impl OpenOptions { if self.truncate && !self.create_new { return Err(io::Error::new( io::ErrorKind::InvalidInput, - "creating or truncating a file requires write or append access", + "append and truncate cannot both be enabled", )); } }