# How to print Step.Run stderr only of the step fails?

**URL:** <https://ziggit.dev/t/how-to-print-step-run-stderr-only-of-the-step-fails/9642>\
**Category:** Help\
**Tags:** build-system\
**Created:** [April 15, 2025, 3:26pm UTC](https://ziggit.dev/t/how-to-print-step-run-stderr-only-of-the-step-fails/9642 "2025-04-15T15:26:07Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![matklad](https://ziggit.dev/user_avatar/ziggit.dev/matklad/32/2462_2.png) [@matklad](https://ziggit.dev/u/matklad)\
**Post date:** [April 15, 2025, 3:26pm UTC](https://ziggit.dev/t/how-to-print-step-run-stderr-only-of-the-step-fails/9642/1 "2025-04-15T15:26:07Z")

</div>

I have a Run step which always prints something to stderr. However, I want to see stderr only if the step fails.

If I don’t configure the behavior specially, stderr is inherited, which is not what I want.

If I do `step.addCheck(.{ .expect_term = .{ .Exited = 0 } });`, the stderr is collected, which is good because it at least doesn’t lock build’s global stdio mutex, but it is still printing unconditionally at the end of the build.

If I _also_ `step.addCheck(.{ .expect_stderr_match = "" });`, then `stderr` isn’t printed even if the step is considered failed.

Looking at the relevant build\_runner.zig code, it seems like this use-case isn’t actually supported at all:

```zig
    // No matter the result, we want to display error/warning messages.
    const show_compile_errors = !run.prominent_compile_errors and
        s.result_error_bundle.errorMessageCount() > 0;
    const show_error_msgs = s.result_error_msgs.items.len > 0;
    const show_stderr = s.result_stderr.len > 0;

    if (show_error_msgs or show_compile_errors or show_stderr) {
        var bw = std.debug.lockStdErr2();
        defer std.debug.unlockStdErr();

        const gpa = b.allocator;
        const options: std.zig.ErrorBundle.RenderOptions = .{
            .ttyconf = run.ttyconf,
            .include_reference_trace = (b.reference_trace orelse 0) > 0,
        };
        printErrorMessages(gpa, s, options, &bw, run.prominent_compile_errors) catch {};
    }

```

But is there perhaps some out-of-the-box way to do what I want here?

---

<div class="post-metadata">

**Author:** ![mnemnion](https://ziggit.dev/user_avatar/ziggit.dev/mnemnion/32/2478_2.png) [@mnemnion](https://ziggit.dev/u/mnemnion)\
**Post date:** [April 15, 2025, 5:11pm UTC](https://ziggit.dev/t/how-to-print-step-run-stderr-only-of-the-step-fails/9642/2 "2025-04-15T17:11:13Z")

</div>

I believe [Run.captureStdErr](https://ziglang.org/documentation/0.14.0/std/#std.Build.Step.Run.captureStdErr) might do the trick. You’ll need logic in the build to open and print the file, though. I’ve only used it to discard spurious output.

---

<div class="post-metadata">

**Author:** ![matklad](https://ziggit.dev/user_avatar/ziggit.dev/matklad/32/2462_2.png) [@matklad](https://ziggit.dev/u/matklad)\
**Post date:** [April 21, 2025, 3:59pm UTC](https://ziggit.dev/t/how-to-print-step-run-stderr-only-of-the-step-fails/9642/3 "2025-04-21T15:59:33Z")

</div>

Got it working with

```zig
fn hide_stderr(run: *std.Build.Step.Run) void {
    const b = run.step.owner;

    run.addCheck(.{ .expect_term = .{ .Exited = 0 } });
    run.has_side_effects = true;

    const override = struct {
        var global_map: std.AutoHashMapUnmanaged(usize, std.Build.Step.MakeFn) = .{};

        fn make(step: *std.Build.Step, prog_node: std.Progress.Node) anyerror!void {
            const original = global_map.get(@intFromPtr(step)).?;
            try original(step, prog_node);
            assert(step.result_error_msgs.items.len == 0);
            step.result_stderr = "";
        }
    };

    const original = run.step.makeFn;
    override.global_map.put(b.allocator, @intFromPtr(&run.step), original) catch @panic("OOM");
    run.step.makeFn = &override.make;
}

```

Please don’t show this code to Andrew, otherwise he might reconsider private fields.

---

<div class="post-metadata">

**Author:** ![vulpesx](https://ziggit.dev/user_avatar/ziggit.dev/vulpesx/32/3989_2.png) [@vulpesx](https://ziggit.dev/u/vulpesx)\
**Post date:** [April 22, 2025, 3:59am UTC](https://ziggit.dev/t/how-to-print-step-run-stderr-only-of-the-step-fails/9642/4 "2025-04-22T03:59:58Z")

</div>

Non-private fields are precisely so you can do things that API doesn’t expose

---

<div class="post-metadata">

**Author:** ![alexrp](https://ziggit.dev/user_avatar/ziggit.dev/alexrp/32/2793_2.png) [@alexrp](https://ziggit.dev/u/alexrp)\
**Post date:** [April 25, 2025, 8:24pm UTC](https://ziggit.dev/t/how-to-print-step-run-stderr-only-of-the-step-fails/9642/5 "2025-04-25T20:24:11Z")

</div>

This seems like a reasonable use case for us to support. Maybe file an enhancement issue?
