Panic when using collectOutput with std.process.Child

I’m trying to spawn a subprocess and capture its stdout and stderr using Zig’s std.process.Child. However, I’m encountering a panic with the error attempt to use null value when calling collectOutput.
Here’s the relevant code:

pub fn spawnAndWaitBasic(self: *Shell, command: []const u8, args: ArrayList([]const u8)) !ProcOutput {
    var argv = ArrayList([]const u8).init(self.allocator);
    try argv.append(command);
    try argv.appendSlice(args.items);

    var child_proc = std.process.Child.init(argv.items, self.allocator);
    child_proc.stdout_behavior = .Pipe;
    child_proc.stderr_behavior = .Pipe;
    const term = try child_proc.spawnAndWait();
    if (term != .Exited) {
        return CommandError.GenericError;
    }

    const maxSize = 1024;
    var procStout = try std.ArrayList(u8).initCapacity(self.allocator, maxSize);
    var procStderr = try std.ArrayList(u8).initCapacity(self.allocator, maxSize);
    try child_proc.collectOutput(&procStout, &procStderr, maxSize * 2);

    return ProcOutput{ .stdout = procStout.items, .stderr = procStderr.items };
}

When I run this, I get the following panic:

thread 99156 panic: attempt to use null value
/usr/lib/zig/std/process/Child.zig:348:31: 0x1043c2d in collectOutput (main)
        .stdout = child.stdout.?,
                              ^
/home/xx/src/main.zig:316:37: 0x1044932 in spawnAndWaitBasic (main)
        try child_proc.collectOutput(&procStout, &procStderr, maxSize * 2);
  • Why is child.stdout null even though I set stdout_behavior to .Pipe?
  • Am I missing a step in setting up the child process or handling its output?
  • Is there a better way to capture stdout and stderr from a subprocess in Zig?

Any help or guidance would be greatly appreciated!

Oh

spawnAndWait waits for the process to finish but does not retain the pipes, which is why child.stdout is null.

Using spawn instead of spawnAndWait** with .wait helped!

1 Like