Stream: beginners

Topic: Basic-cli: Cmd.exec errors in if block, but not outside.


view this post on Zulip Ian McLerran (May 25 2024 at 19:20):

So I've encountered what appears to be a bug in the basic-cli platform. I have an if block, in which I follow two nearly identical code paths depending on weather a file exists. I call Cmd.exec! "nano" ["filename.txt"], and then continue with my program when the editor exits.

This works fine, if I do not check for the file's existence ahead of time. However if I place the Cmd.exec call inside an if block, I get a CmdError ExecutableFileBusy error after the exec task completes.

Code is below (note that the bugged version is uncommented, however the commented out code works):

main =
    isFile = Path.isFile (Path.fromStr "config.rvn")
        |> Task.attempt! \res ->
            when res is
                Ok bool -> Task.ok bool
                _ -> Task.ok Bool.false
    if isFile then
        Stdout.line! "config file found"
        Cmd.exec! "nano" ["config.rvn"]
        contents = File.readUtf8! "config.rvn"
        Stdout.line! "file contents: $(contents)"
    else
        Stdout.line! "config file not found"
        File.writeUtf8! "config.rvn" configTemplate
        Cmd.exec! "nano" ["config.rvn"]
        contents = File.readUtf8! "config.rvn"
        Stdout.line! "file contents: $(contents)"

# main =
#     File.writeUtf8! "config.rvn" configTemplate
#     Cmd.exec! "nano" ["config.rvn"]
#     contents = File.readUtf8! "config.rvn"
#     Stdout.line! "file contents: $(contents)"

The bug happens for both basic-cli v0.10.0 and v0.11.0.

view this post on Zulip Luke Boswell (May 25 2024 at 19:27):

I'm guessing Path.isFile isn't finished with the file handle before the Cmd.exec runs. What happens if you add a small sleep in there?

view this post on Zulip Ian McLerran (May 25 2024 at 19:31):

Good question... I'll check. I should also note that the following works:

main =
    createFileIfNone!
    File.writeUtf8! "config.rvn" configTemplate
    Cmd.exec! "nano" ["config.rvn"]
    contents = File.readUtf8! "config.rvn"
    Stdout.line! "file contents: $(contents)"

createFileIfNone =
    isFile = Path.isFile (Path.fromStr "config.rvn")
        |> Task.attempt! \res ->
            when res is
                Ok bool -> Task.ok bool
                _ -> Task.ok Bool.false
    if isFile then
        File.writeUtf8 "config.rvn" configTemplate
    else
        Task.ok {}

view this post on Zulip Luke Boswell (May 25 2024 at 19:32):

https://github.com/roc-lang/basic-cli/blob/592a4a950e16c09c205e298f272381102f49f756/platform/src/lib.rs#L502

view this post on Zulip Luke Boswell (May 25 2024 at 19:32):

Here'd the specific implementation of that Path.isFile effect

view this post on Zulip Ian McLerran (May 25 2024 at 19:36):

I’m computer right now so can’t test sleep immediately, but I should also mention, even in the bugged code, File.write successfully creates the file, and nano is able to open the newly created file.

view this post on Zulip Luke Boswell (May 25 2024 at 19:38):

Interesting. Seems a bit strange. Maybe we could provide more context back in the error. Worth looking into as well. Or adding some dbg statements in the platform.

view this post on Zulip Ian McLerran (May 25 2024 at 20:24):

Ok, yes, adding a 1ms sleep does resolve the issue. Interesting, because I put the sleep immediately before Cmd.exec, and after File.writeUtf8.

view this post on Zulip Ian McLerran (May 25 2024 at 20:32):

So file.write does not conflict with the exec command, and regardless of how I write this code, nano always successfully opens the file:

However, if I call exec inside of the if block, after nano exits, I see that the roc program crashed. But no crash occurs if


Last updated: Jul 06 2025 at 12:14 UTC