async-rs / async-std

Async version of the Rust standard library

Home Page:https://async.rs

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Error information from fs operations not displayed when printing errors

harmic opened this issue · comments

With this code:

	let file_name = Path::new("/tmp/does_not_exist/test");

	match fs::File::create(file_name) {
		Ok(_) => (),
		Err(e) => {
			println!("Sync: Error opening file {}: {}", file_name.display(), e);
		}
	};

	async_std::task::block_on(async {
		match async_std::fs::File::create(file_name).await {
			Ok(_) => (),
			Err(e) => {
				println!("Async: Error opening file {}: {}", file_name.display(), e);
			}
		};
	});

We get this output:

Sync: Error opening file /tmp/does_not_exist/test: No such file or directory (os error 2)
Async: Error opening file /tmp/does_not_exist/test: could not create `/tmp/does_not_exist/test`

There are two problems with this:

  • The async version doesn't output the actual reason that the operation failed
  • The async version adds the filename as context. While arguably the std version should do that as well - it doesn't, meaning that if you use the async API in the same way as the sync API, it prints the filename twice.

The first point is the most important. Although more error information is available by inspecting kind or source, I think the Display implementation should include the actual cause of the error.

I don't view the second point as critical, as long as async_std supplies the context for every relevant API and also documents that divergance from std::fs on the doc page for async_std::fs (although I guess a major selling point of async-std is that the API mirrors std).

Seems like context!() has a little bit more invocations. Maybe it's possible to remove them and wait for stdlib to provide additional context to the errors? Not knowing why my CLI or daemon cannot open a file or send data to the socket is pretty bad UX.

I just got bitten by this again.

I can see two options for a fix:

  1. Remove all calls to context so that the errors from async-std align with std. Personally I prefer this, but it does mean that people's existing code will suddenly lose whatever context they had. (Similar to @jaztec's PR but applied throughout).

  2. Improve the implementation of Display for VerboseError (the wrapping struct used by context so that it displays the content of the source error as well as the context.

I'm happy to put together a PR for whichever of these two is going to be accepted.

Well, I think it would be really handy to just implement option 1 and hope for the std library to implement its own version of context. Removing all calls to context would remove complexity from this library and move it back to the standard library as a neat feature. I'm not strong on Rust but having a context decoration doesn't need to be really complex I would say (coming from Go in this matter).

However this PR didn't get much feedback, so either the community isn't really affected by it or the maintainers don't really consider it a problem; probably both. I'm interested though in looking into option 2 since I still need more hands-on experience in Rust development and am willing to submit a PR, although I would like to get some feedback from the maintainers on the requirements to get it approved.