File.stream! has a line that’s easy to miss in the docs:
Operating the stream can fail on open for the same reasons as
File.open!/2
“Operating” is the key part - you can File.stream! things that don’t exist, and you won’t get the exception until something forces the stream.
For instance:
iex(1)> File.stream!("nosuchfile.txt")
%File.Stream{
line_or_bytes: :line,
modes: [:raw, :read_ahead, :binary],
path: "nosuchfile.txt",
raw: true
}
iex(2)> File.stream!("nosuchfile.txt") |> Enum.to_list()
** (File.Error) could not stream "nosuchfile.txt": no such file or directory
(elixir 1.13.0) lib/file/stream.ex:83: anonymous fn/3 in Enumerable.File.Stream.reduce/3
(elixir 1.13.0) lib/stream.ex:1517: anonymous fn/5 in Stream.resource/3
(elixir 1.13.0) lib/enum.ex:4143: Enum.reverse/1
(elixir 1.13.0) lib/enum.ex:3488: Enum.to_list/1
IO.stream can’t fail in any of these ways since it takes either a PID (that you’d get from calling File.open! and possibly getting an exception) or an atom (to refer to stdio), so it doesn’t get a !.






















