I ran across an error like this:
── TYPE MISMATCH ───────────────────────────── examples/interactive/rocsay.roc ─
This 2nd argument to await has an unexpected type:
24│> template <- File.readUtf8 templatePath |> Task.await
25│>
26│> roc = template
27│> |> Result.try (\t -> Str.replaceEach t "\\t" top)
...
33│> |> Result.withDefault "Templating failed!"
34│>
35│> Stdout.line "\(roc)"
The argument is an anonymous function of type:
Result Str [NotFound]* -> Task ...
But await needs its 2nd argument to be:
Str -> Task ...
I did a double-take at "This 2nd argument to await" before realising that backpassing is similar to bind in do-notation (with await being an explicit bind). So it must desugar to an anonymous function and it makes sense that it's passed to await. It took a moment to jump through these steps though, and I don't think I would've gotten it if I hadn't used bind before. I also had an expectation from other languages that await would take a single Promise/Task arg and produce a value.
I know backpassing is covered in the tutorial and will likely remain a part of learning Roc, but would it be useful to have a line showing the desugared function? Something like this:
── TYPE MISMATCH ───────────────────────────── examples/interactive/rocsay.roc ─
This 2nd argument to await has an unexpected type:
24│> template <- File.readUtf8 templatePath |> Task.await
25│>
26│> roc = template
...
Backpassing with <- is desugared to a function that's passed as an argument
on the right side of <- like this:
24│> File.readUtf8 templatePath |> Task.await (\template ->
25│>
26│> roc = template
The argument is an anonymous function of type:
Result Str [NotFound]* -> Task ...
But await needs its 2nd argument to be:
Str -> Task ...
Does the desugared form make it clearer how await is taking a second argument? Is it worth adding this to the error message?
I think the error message should be improved to say something like "this backpassed function has type ..." instead of the "2nd argument" message it mentions now. I think elaborating the desugared form makes sense in a context where we go into more detail about the error (e.g. in a webpage linked from the error, or something like rustc explain). I'd be a bit hesitant about adding it to all error messages, because it might be a bit noisy once you are familiar with backpacking (and there is a better error message), just my opinion though
yeah that seems like a good incremental improvement!
I wonder what the with syntax we've discussed could unlock in terms of error message quality in this case :thinking:
Great point, @doubledup - no matter how we improve that, we definitely should
A separate webpage is a great idea. I cut out a lot of the error message and it's already quite long. Can definitely see it being noisy when you're already familiar with backpassing.
Last updated: Jun 16 2026 at 16:19 UTC